How to pull unique data with retrofit - java

I'm trying to pull some data from a retrofit API and it's JSON looks like this:
{
"data":{
"id":"1",
"type": null,
"links":{
"self":null
},
"attributes":{
"createdAt":null,
"updatedAt":null,
"slug":"teste",
"synopsis":"text",
Then I try to get the specific data like this:
Model:
public class Data {
private ArrayList<Movie> data;
public ArrayList<Movie> getData() {
return data;
}
public void setData(ArrayList<Animes> data) {
this.data = data;
}
}
public class Movie {
private String id;
private Attributes attributes;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Attributes getAttributes() {
return attributes;
}
public void setAttributes(Attributes attributes) {
this.attributes = attributes;
}
}
ApiService:
#GET("movie/{id}")
Call<Data> obtainProfile(#Path("id") int id);
int id = getIntent().getIntExtra("ID", 0);
private void obtainData(final int id) {
ApiService service = retrofit.create(ApiService.class);
Call<Data> profileCall = service.obtainProfile(id);
profileCall.enqueue(new Callback<Data>() {
#Override
public void onResponse(Call<Data> call, Response<Data> response) {
if (response.isSuccessful()) {
Data data = response.body();
Movie Movie = data.getData().get(0);
Attributes attributes = movie.getAttributes();
textName.setText(attributes.getCanonicalTitle());
} else {
Log.e("INFO", "onResponse" + response.errorBody());
Toast.makeText(PerfilActivity.this, "Error connecting to server.", Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<Data> call, Throwable t) {
Log.e("INFO", "onErro" + t.getMessage());
}
});
}
How can I solve this? I tried but I can not view the data.
Will I have to create a list for this?
How can I solve this? I tried but I can not view the data.
Will I have to create a list for this?

Change your ArrayList<Movie> to just Movie.
Also create another class:
public class DataResponse {
public Data data;
}
And change your Retrofit method to this:
#GET("movie/{id}")
Call<DataResponse> obtainProfile(#Path("id") int id);

Related

How to implelement this on retrofit?

Hello I am an android developer and i have never before faced this problem before "Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $" i am suspecting the issue is in my model.
this is the postman response as is
{
"Status": 200,
"Message": "OK",
"Data": {
"ServiceTypes": [
{
"Id": 1,
"ServiceTypeNameAr": "صيانة",
"ServiceTypeNameEn": "Maintenance",
"MainServices": [
{
"Id": 11,
"ServiceTypeId": 1,
"MainServiceNameAr": "تكييفات\r\n",
"MainServiceNameEn": "Air conditioning\r\n",
"SubServices": null
},
{
"Id": 12,
"ServiceTypeId": 1,
"MainServiceNameAr": "كهرباء\r\n",
"MainServiceNameEn": "Electricity\r\n",
"SubServices": null
},
{
"Id": 14,
"ServiceTypeId": 1,
"MainServiceNameAr": "سباكة",
"MainServiceNameEn": "Plumbing\r\n",
"SubServices": null
},
{
"Id": 15,
"ServiceTypeId": 1,
"MainServiceNameAr": "اجهزة منزلية\r\n",
"MainServiceNameEn": "Home appliances\r\n",
"SubServices": null
}
]
}
]
}
}
i want to implement this as a pojo(model) in my code this is my try (Edited)
ResponseModel
public class ResponseModel {
#SerializedName("Status")
public int Status;
#SerializedName("Message")
public String Message;
#SerializedName("Data")
public DataModel Data;
public int getStatus() {
return Status;
}
public void setStatus(int status) {
Status = status;
}
public String getMessage() {
return Message;
}
public void setMessage(String message) {
Message = message;
}
public DataModel getData() {
return Data;
}
public void setData(DataModel data) {
this.Data = data;
}
}
DataModel
public class DataModel {
#SerializedName("Country")
private List<CountryModel> countryModels;
#SerializedName("Users")
private List<UserModel> users;
#SerializedName("Cities")
private List<CityItem> cityItems;
#SerializedName("ServiceTypes")
private List<ServiceTypeModel> serviceTypeModels;
private Map<String, Object> additionalProperties = new HashMap<String,
Object>();
public List<CityItem> getCityItems() {
return cityItems;
}
public void setCityItems(List<CityItem> cityItems) {
this.cityItems = cityItems;
}
public List<UserModel> getUsers() {
return users;
}
public void setUsers(ArrayList<UserModel> users) {
this.users = users;
}
public List<CountryModel> getCountryModels() {
return countryModels;
}
public void setCountryModels(ArrayList<CountryModel> countryModels) {
this.countryModels = countryModels;
}
public List<ServiceTypeModel> getServiceTypeModels() {
return serviceTypeModels;
}
public void setServiceTypeModels(List<ServiceTypeModel> serviceTypeModels) {
this.serviceTypeModels = serviceTypeModels;
}
public void setCountryModels(List<CountryModel> countryModels) {
this.countryModels = countryModels;
}
public void setUsers(List<UserModel> users) {
this.users = users;
}
public Map<String, Object> getAdditionalProperties() {
return additionalProperties;
}
public void setAdditionalProperties(Map<String, Object> additionalProperties) {
this.additionalProperties = additionalProperties;
}
}
ServiceTypeModel
public class ServiceTypeModel {
#SerializedName("Id")
private int id;
#SerializedName("ServiceTypeNameAr")
private String serviceTypeNameAr;
#SerializedName("ServiceTypeNameEn")
private String serviceTypeNameEn;
#SerializedName("MainServices")
private List<MainServicesModel> mainServicesList;
public List<MainServicesModel> getMainServicesList() {
return mainServicesList;
}
public void setMainServicesList(List<MainServicesModel> mainServicesList) {
this.mainServicesList = mainServicesList;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getServiceTypeNameAr() {
return serviceTypeNameAr;
}
public void setServiceTypeNameAr(String serviceTypeNameAr) {
this.serviceTypeNameAr = serviceTypeNameAr;
}
public String getServiceTypeNameEn() {
return serviceTypeNameEn;
}
public void setServiceTypeNameEn(String serviceTypeNameEn) {
this.serviceTypeNameEn = serviceTypeNameEn;
}
}
The Interface:
public interface ServiceTypeInterface {
#GET("ServiceType")
public Call<ResponseModel> GetServicesType(#Header("authorization") String token);
#GET("ServiceType/{id}")
public Call<ResponseModel> GetServiceTypeById(#Path("id") int Id, #Header("authorization") String token);
}
Adapter
public class ServiceTypeAdapter extends RecyclerView.Adapter<ServiceTypeAdapter.ServiceTypeHolder> {
private List<ResponseModel> serviceTypeModels = new ArrayList<>();
private final ServiceTypeListener listener;
private Context context;
public ServiceTypeAdapter(ServiceTypeListener listener, Context context, List<ResponseModel> serviceTypeList) {
this.listener = listener;
this.context = context;
this.serviceTypeModels = serviceTypeList;
}
#NonNull
#Override
public ServiceTypeHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_sub_service, parent, false);
return new ServiceTypeHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull ServiceTypeHolder holder, int position) {
final ResponseModel ServiceType = serviceTypeModels.get(position);
holder.TxtServiceTypeName.setText(ServiceType.getData().getServiceTypeModels().get(0).getServiceTypeNameEn());
}
#Override
public int getItemCount() {
return serviceTypeModels.size();
}
public long getItemId(int position) {
return position;
}
public void setList(List<ResponseModel> serviceTypeModels) {
// serviceTypeModels = new List<ResponseModel>(serviceTypeModels.get(0).getData().getServiceTypeModels().get(0).getServiceTypeNameEn());
this.serviceTypeModels = serviceTypeModels;
notifyDataSetChanged();
}
public class ServiceTypeHolder extends RecyclerView.ViewHolder {
TextView TxtServiceTypeName;
public ServiceTypeHolder(#NonNull View itemView) {
super(itemView);
TxtServiceTypeName = itemView.findViewById(R.id.ServiceTypeName);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
listener.onServiceTypeSelected(serviceTypeModels.get(getAdapterPosition()));
}
});
}
}
public interface ServiceTypeListener {
void onServiceTypeSelected(ResponseModel serviceTypeModel);
}
}
i tried to separate them as well into two models the status, message and data which calls for the services type which is in another model.
if anything else or more clarification is needed pls don't hesitate to ask me for code or anything.
any help is really appreciated.
Thanks in advance.
you may implement pojo as this:
this class represent the top level object:
public class ResponseModel {
private Integer Status;
private String Message;
private DataModel Data;
// getters, setters, constructors
}
this class represents Data class:
public class DataModel {
private List<ServiceTypeModel> ServiceTypes;
// getters, setters, constructors
}
and this class maps with ServiceTypes
public class ServiceTypeModel {
private Long Id;
private String ServiceTypeNameAr;
private String ServiceTypeNameEn;
private List<MainServiceModel> MainServices;
// getters, setters, constructors
}
And finally this class maps with MainServices
public class MainServiceModel{
private Long Id;
private Long ServiceTypeId;
private String MainServiceNameAr;
private String MainServiceNameEn;
private List<SubServiceModel> SubServices;
// getters, setters, constructors
}
for SubServices, you have provided null so I imagine this is a List of SubServiceModel. You can implement this class like how I did for the others.
Also you can use some online tools to generate pojo of a json like this
I think the problem is with your ServiceTypeWebEntity model where you set data as a list but it's an object which has ServiceTypes key with List<ServiceTypeModel> inside, so you can try this model.
public class ServiceTypeWebEntity {
#SerializedName("Status")
private int Status;
#SerializedName("Message")
private String Message;
#SerializedName("data")
public ServiceTypes ServicesType;
public int getStatus() {
return Status;
}
public void setStatus(int status) {
Status = status;
}
public String getMessage() {
return Message;
}
public void setMessage(String message) {
Message = message;
}
public ServiceTypes getServicesType() {
return ServicesType;
}
public void setServicesType(ServiceTypes servicesType) {
ServicesType = servicesType;
}
public class ServiceTypes{
#SerializedName("ServiceTypes")
public List<ServiceTypeModel> ServicesType;
public List<ServiceTypeModel> getServicesType() {
return ServicesType;
}
public void setServicesType(List<ServiceTypeModel> servicesType) {
ServicesType = servicesType;
}
}
public class ServiceTypeModel {
#SerializedName("Id")
private int id;
#SerializedName("ServiceTypeNameAr")
private String serviceTypeNameAr;
#SerializedName("ServiceTypeNameEn")
private String serviceTypeNameEn;
#SerializedName("MainServices")
private List<MainServicesModel> mainServicesList;
public List<MainServicesModel> getMainServicesList() {
return mainServicesList;
}
public void setMainServicesList(List<MainServicesModel> mainServicesList) {
this.mainServicesList = mainServicesList;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getServiceTypeNameAr() {
return serviceTypeNameAr;
}
public void setServiceTypeNameAr(String serviceTypeNameAr) {
this.serviceTypeNameAr = serviceTypeNameAr;
}
public String getServiceTypeNameEn() {
return serviceTypeNameEn;
}
public void setServiceTypeNameEn(String serviceTypeNameEn) {
this.serviceTypeNameEn = serviceTypeNameEn;
}
}
}
hope it helps.
I knew where i was wrong i was missing a small part in my main for calling the list itself here is the main for anyone who needs it or anyone facing the same issue
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_categories);
//
TestTxt = findViewById(R.id.TestTxt);
serviceTypeViewModel = ViewModelProviders.of(this).get(ServiceTypeViewModel.class);
serviceTypeViewModel.GetServiceType();
serviceTypeRecycler = findViewById(R.id.ServiceTypeRV);
// LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
// serviceTypeRecycler.setLayoutManager(layoutManager);
// serviceTypeRecycler.setItemAnimator(new DefaultItemAnimator());
// serviceTypeRecycler.setAdapter(serviceTypeAdapter);
FillListServices();
}
private void FillListServices() {
serviceTypeViewModel.ServiceTypeMutableLiveData.observe(this, new Observer<ResponseModel>() {
// Here i was trying to call the ServiceTypeModel instead
#Override
public void onChanged(ResponseModel responseModel) {
Utilities.dismissLoadingDialog();
serviceTypeModelArrayList = new ArrayList<>();
serviceTypeModelArrayList = responseModel.getData().getServiceTypeModels();
TestTxt.setText(responseModel.getData().getServiceTypeModels().get(0).getServiceTypeNameAr());
serviceTypeAdapter = new ServiceTypeAdapter(responseModel.getData().getServiceTypeModels());
LinearLayoutManager layoutManager = new LinearLayoutManager(MainCategories.this, LinearLayoutManager.HORIZONTAL, false);
serviceTypeRecycler.setLayoutManager(layoutManager);
serviceTypeRecycler.setAdapter(serviceTypeAdapter);
}
});
}

Parsing JSON with GSON without knowing the value format

hi guys i have a api like this you can see i have a metaData array and all of the items in the array have a Integer id and a string key but value is not the same in all of them i defined the value in the Object but i have an error this is the error
Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 3871 path $[0].meta_data
and this is my POJO class
Main Pojo(Product) class
#SerializedName("meta_data")
#Expose
private MetaDatum metaData;
and this is the MetaDatum Class
public class MetaDatum implements Parcelable {
#SerializedName("id")
#Expose
private Integer id;
#SerializedName("key")
#Expose
private String key;
#SerializedName("value")
#Expose
private Object value;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(this.id);
dest.writeString(this.key);
dest.writeParcelable((Parcelable) this.value, flags);
}
public MetaDatum() {
}
protected MetaDatum(Parcel in) {
this.id = (Integer) in.readValue(Integer.class.getClassLoader());
this.key = in.readString();
this.value = in.readParcelable(Object.class.getClassLoader());
}
public static final Parcelable.Creator<MetaDatum> CREATOR = new Parcelable.Creator<MetaDatum>() {
#Override
public MetaDatum createFromParcel(Parcel source) {
return new MetaDatum(source);
}
#Override
public MetaDatum[] newArray(int size) {
return new MetaDatum[size];
}
};
}
make all pojo class for your json data using robopojo puligns or http://www.jsonschema2pojo.org/
after that make retrofit object define base url and other things...
public class ApiClient {
private final static String BASE_URL = "https://goorab.com/wp-json/wc/v2/";
public static ApiClient apiClient;
private Retrofit retrofit = null;
public static ApiClient getInstance() {
if (apiClient == null) {
apiClient = new ApiClient();
}
return apiClient;
}
//private static Retrofit storeRetrofit = null;
public Retrofit getClient() {
return getClient(null);
}
private Retrofit getClient(final Context context) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.readTimeout(60, TimeUnit.SECONDS);
client.writeTimeout(60, TimeUnit.SECONDS);
client.connectTimeout(60, TimeUnit.SECONDS);
client.addInterceptor(interceptor);
client.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
return chain.proceed(request);
}
});
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client.build())
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit;
}
}
and make interface for api calling..
public interface ApiInterface {
#GET("products")
Call<ResponseData> getdata(#Query("consumer_key") String key);
}
after that calling into activity or fragment like below.
ApiInterface apiInterface = ApiClient.getInstance().getClient().create(ApiInterface.class);
Call<ResponseData> responseCall = apiInterface.getdata("pass key");
responseCall.enqueue(new Callback<ResponseData>() {
#Override
public void onResponse(Call<ResponseData> call, retrofit2.Response<ResponseData> response) {
if (response.isSuccessful() && response.body() != null && response != null) {
Toast.makeText(getApplicationContext(), "GetData" + response.body().getLanguage(), Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<ResponseData> call, Throwable t) {
Log.d("Errror", t.getMessage());
}
});
and make sure pojo class are all valid.
All Unicode characters may be placed within the quotation marks except for the characters that must be escaped: quotation mark, reverse solidus, and the control characters (U+0000 through U+001F)
Your meta_data is array instead of object
meta_data": [
{
"id": 3281,
"key": "_vc_post_settings",
"value": {
"vc_grid_id": []
}
]
So use List
private List<MetaDatum> metaData;

Room #Insert does not insert all records

I am running into an issue where only 1 record is being inserted into my Room SQLite DB.
When I perform a getAll(); the result only returns 1 record.
FOUND ISSUE: Genre[] genres = gson.fromJson(jsonArray.toString(), Genre[].class);
This line above is setting all "gid" values to 0, and I am not sure how to change that.
Genre.java
#Entity(indices = {#Index(value = {"id", "name"}, unique = true)})
public class Genre {
#PrimaryKey
private int gid;
//#ColumnInfo(name = "id") By Default - No need to annotate
#NonNull
private int id;
private String name;
public int getGid() {
return gid;
}
public void setGid(int gid) {
this.gid = gid;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
GenreDao.java
#Dao
public interface GenreDao {
#Query("SELECT * FROM Genre")
LiveData<List<Genre>> getAll();
#Insert(onConflict = OnConflictStrategy.REPLACE) //If there is a conflict, replace the record.
void insertAll(Genre... genres);
}
GenreRepository.java
public class GenreRepository {
private final GenreDao genreDao;
public GenreRepository(GenreDao genreDao) {
this.genreDao = genreDao;
}
//Database Methods
public void insertAll(Genre... genres) {
AsyncTask.execute(() -> { //Same as new Runnable()
genreDao.insertAll(genres);
});
}
public LiveData<List<Genre>> getAll() {
return genreDao.getAll();
}
}
APIUtil.java - getGenres() Method
This class makes an API call, returns the proper results, converts the JSONArray to a Genre[]. I can successfully loop through the Genre[] and confirm 10+ results come back.
public static void getGenres(Context context) {
APIWrapper wrapper = new APIWrapper(context, API_KEY);
Parameters params = new Parameters();
params.addFields(GENRE_FIELDS);
params.addLimit("50");
wrapper.genres(params, new onSuccessCallback() {
#Override
public void onSuccess(JSONArray jsonArray) {
Gson gson = new Gson();
Genre[] genres = gson.fromJson(jsonArray.toString(), Genre[].class);
//Insert DB
AppDatabase db = AppDatabase.getAppDatabase(context);
GenreRepository genreRepository = new GenreRepository(db.genreDao());
genreRepository.insertAll(genres);
}
#Override
public void onError(VolleyError volleyError) {
Log.e("GENRES ERROR:", volleyError.toString());
}
});
}
GenreViewModel.java
public class GenreViewModel extends ViewModel {
private GenreRepository genreRepository;
public GenreViewModel(GenreRepository genreRepository) {
this.genreRepository = genreRepository;
}
public void insertAll(Genre... genres){
genreRepository.insertAll(genres);
}
public LiveData<List<Genre>> getAll(){
return genreRepository.getAll();
}
}
SearchFragment.java
This is where I am retrieving the database values. This for loop only returns 1 result.
AppDatabase db = AppDatabase.getAppDatabase(getActivity());
GenreRepository genreRepository = new GenreRepository(db.genreDao());
GenreViewModel genreViewModel = new GenreViewModel(genreRepository);
genreViewModel.getAll().observe(this, genres -> { //new Observer<List<Genre>>()
for(Genre g : genres){
Log.e("GENRE", g.getName());
}
});
public void insertAll(Genre... genres){
genreRepository.insertAll(genres);
}
here is your mistake , what you provide as method definition and what you provide at call. see you make some thing wrong.
Solution
void insertAll(List<T> obj);
you can try with convert your array to list and put above in definition
I had this problem too.
And Solved it this way.
The problem was that the id that comes from server was mongoId and String so I should create a int primary key and pass currentTime as value to it so the database can insert all of them not replace them.
But you should consider using System.nanoTime() method instead of System.currentTimeMillis() cause sometimes it generates same value and then room replace them instead of inserting each one of them.

Expected BEGIN_ARRAY but was BEGIN_OBJECT retrofit2

I have some problem about retrofit2
How to fix Expected BEGIN_ARRAY but was BEGIN_OBJECT in retrofit2
I don't know to fix it
What's my wrong ?
my json is
{
"result": true,
"message": "success",
"data": [
{
"id": "10",
"type_name": "pppppp"
},
{
"id_mt": "11",
"type_name": "aaaaaa"
}
]
}
and my model class is
public class MessageFastModel {
private boolean result;
private String message;
private List<DataBean> data;
public boolean isResult() {
return result;
}
public void setResult(boolean result) {
this.result = result;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public List<DataBean> getData() {
return data;
}
public void setData(List<DataBean> data) {
this.data = data;
}
public static class DataBean {
private String id;
private String type_name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType_name() {
return type_name;
}
public void setType_name(String type_name) {
this.type_name = type_name;
}
}
}
My code is
#FormUrlEncoded
#POST("api/message_type")
Call<MessageFastModel> listMessageFast(#Field("token") String token);
and
Call<MessageFastModel> dddddCall = ooooo.listMessageFast(Preferences.getToken());
dddddCall.enqueue(new Callback<MessageFastModel>() {
#Override
public void onResponse(Call<MessageFastModel> call, Response<MessageFastModel> response) {
if (response.isSuccessful()) {
Log.d("ddd", "onResponse: " + response.body().getData().size());
}
}
#Override
public void onFailure(Call<MessageFastModel> call, Throwable t) {
Log.e("ddd", "onFailure: " + t.getMessage());
}
});
but My error is
E/ddd: onFailure: java.lang.IllegalStateException: Expected
BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 44 path $.data
what's problem ? thanks!
#GET("photos")
Call<Model> savePhoto();
And Call your retrofit method like this >>>
Call<Model> call = apiService.savePhoto();
call.enqueue(new retrofit2.Callback<Model>() {
#Override
public void onResponse(Call<Model> call, retrofit2.Response<Model> response) {
int statusCode = response.code();
try {
Model model;
// Log.w("resedatasync", new Gson().toJson(response));
model= response.body();
And Create Your Model Class like this
public class Model{
#SerializedName("ArrayName")
public List<DataBean > arraylist= new ArrayList<>();
#SerializedName("message")
private String message;
public class DataBean {
#SerializedName("id")
private String id;
#SerializedName("typename")
private String typename;
#SerializedName("typename")
public void settypename(String typename) {
this.typename= typename;
}
}
}
When you have problem
java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 44 path $.data
We must know that where need JSONArray .You have List<DataBean> data .So your data must use JSONArray .
And may be your problem at
Log.d("ddd", "onResponse: " + response.body().getData().size());
You can do like this .
System.out.println(response.body().string());
And show your message .
And try this class .
public class MessageFastModel {
private boolean result;
private String message;
private DataBean data;
public boolean isResult() {
return result;
}
public void setResult(boolean result) {
this.result = result;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public DataBean getData() {
return data;
}
public void setData(DataBean data) {
this.data = data;
}
public static class DataBean {
private String id;
private String type_name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType_name() {
return type_name;
}
public void setType_name(String type_name) {
this.type_name = type_name;
}
}
}
And remove Log.d("ddd", "onResponse: " + response.body().getData().size());
This happens when the structure of JSON doesn't matches with the structure of your recipient model class. Also use #Expose and #SerializedName("receivingJsonVariableName") for each variable in the model class.

How to access data inside my ArrayList<Parcelable>

This is my scenario. I get data from a web service and display those data in recycler view. After that I'm planing to add those data in to local sqlite database and display those data when user open application without internet connection. I decided to use IntentService for this so I can save those data without blocking main thread.
I'm using retrofit, GSON and RxJAVA combination to take data from REST service.
retrofit = new Retrofit.Builder()
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.build();
public void getAllEvent(){
EventService eventService = retrofit.create(EventService.class);
Single<List<Event>> eventsAsSingle = eventService.getEvents();
eventDisposableSingleObserver = eventsAsSingle
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new DisposableSingleObserver<List<Event>>() {
#Override
public void onSuccess(#NonNull List<Event> events) {
//eventDataList is type of ArrayList<Event>
eventDataList.addAll(events);
EventListAdapter listAdapter = new EventListAdapter(MainActivity.this,eventDataList);
recyclerView.setAdapter(listAdapter);
recyclerView.addItemDecoration(new RecyclerViewDividerVertical(5));
recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));
//TODO: ADD data into SQLight
Intent intent = new Intent(MainActivity.this,EventCacheService.class);
intent.putParcelableArrayListExtra("event_data",eventDataList);
startService(intent);
}
#Override
public void onError(#NonNull Throwable e) {
Log.d(TAG, "on Error : " + e.getMessage());
}
});
}
Here's my Event class.
import android.os.Parcel;
import android.os.Parcelable;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Event implements Parcelable {
#SerializedName("id")
#Expose
private String id;
#SerializedName("type")
#Expose
private String type;
#SerializedName("actor")
#Expose
private Actor actor;
#SerializedName("repo")
#Expose
private Repo repo;
#SerializedName("payload")
#Expose
private Payload payload;
#SerializedName("public")
#Override
public int describeContents() {
return 0;
}
public Event() {
}
protected Event(Parcel in) {
this.id = in.readString();
this.type = in.readString();
this.actor = in.readParcelable(Actor.class.getClassLoader());
this.repo = in.readParcelable(Repo.class.getClassLoader());
this.payload = in.readParcelable(Payload.class.getClassLoader());
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.id);
dest.writeString(this.type);
dest.writeParcelable(this.actor, flags);
dest.writeParcelable(this.repo, flags);
dest.writeParcelable(this.payload, flags);
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Actor getActor() {
return actor;
}
public void setActor(Actor actor) {
this.actor = actor;
}
public Repo getRepo() {
return repo;
}
public void setRepo(Repo repo) {
this.repo = repo;
}
public Payload getPayload() {
return payload;
}
public void setPayload(Payload payload) {
this.payload = payload;
}
public static final Parcelable.Creator<Event> CREATOR = new Parcelable.Creator<Event>() {
#Override
public Event createFromParcel(Parcel source) {
return new Event(source);
}
#Override
public Event[] newArray(int size) {
return new Event[size];
}
};
}
My service class.
public class EventCacheService extends IntentService {
public EventCacheService() {
super("EventCacheService");
}
#Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
ArrayList<Parcelable> eventData = intent.getParcelableArrayListExtra("event_data");
System.out.println("yeee");
}
}
}
If I set a break point on System.out.println() I can see that I have taken all the data from my activity to Service successfully.
But I can't find a way to access those Event type objects. As suggested in most places I can't convert these objects in to Event type by simply doing.
(ArrayList<Event>)intent.getParcelableArrayListExtra("event_data");
I'm getting an error saying Error:(20, 99) error: incompatible types: ArrayList<Parcelable> cannot be converted to ArrayList<Event>
Please point out what I'm going wrong. Is there any better way to handle this ?
You problem is error: incompatible types: ArrayList<Parcelable> cannot be converted to ArrayList<Event>
So change
ArrayList<Parcelable> eventData = intent.getParcelableArrayListExtra("event_data");
to
ArrayList<Event> eventData = intent.getParcelableArrayListExtra("event_data");
Sorry, My bad. I can access those objects like this.
for (Parcelable parceledEvent: eventData){
Event event = (Event) parceledEvent;
String type = event.getType();
Log.d(TAG,"type: "+type);
}

Categories