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);
}
Related
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);
}
});
}
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);
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;
I have an application in which I wanted to store a list of items and I figured a database would do. I found out about the new Room API and tried using it, though I'm having some trouble getting it working. I have a background service which is supposed to write entries to the database. I read that using the singleton pattern was recomended, but I can't seem to get it working. When I try to retrieve all entries in my MainActivity, the list I get back is always empty, indicating that I wasn't able to save them from the start.
Singleton db class
#Database(entities = {TemperatureReading.class}, version = 1)
public abstract class DatabaseSingleton extends RoomDatabase {
private static DatabaseSingleton INSTANCE;
public abstract TemperatureReadingDao temperatureReadingDao();
public static DatabaseSingleton getAppDatabase(Context context) {
if (INSTANCE == null) {
INSTANCE =
Room.databaseBuilder(context.getApplicationContext(), DatabaseSingleton.class, "fireTempDatabase")
.build();
}
return INSTANCE;
}
public static void destroyInstance() {
INSTANCE = null;
}
}
Entity
#Entity
public class TemperatureReading {
#PrimaryKey(autoGenerate = true)
private int uid;
#ColumnInfo(name = "dateTime")
private long dateTime;
#ColumnInfo(name = "location")
private String readingLocation;
#ColumnInfo(name = "value")
private float value;
public long getDateTime() {
return dateTime;
}
public void setDateTime(long dateTime) {
this.dateTime = dateTime;
}
public String getReadingLocation() {
return readingLocation;
}
public void setReadingLocation(String readingLocation) {
this.readingLocation = readingLocation;
}
public float getValue() {
return value;
}
public void setValue(float value) {
this.value = value;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
}
EntityDAO
#Dao
public interface TemperatureReadingDao {
#Query("SELECT * FROM temperatureReading")
List<TemperatureReading> getAll();
#Query("SELECT * FROM temperatureReading ORDER BY uid desc limit 1")
TemperatureReading getLatest();
#Insert
void insertAll(TemperatureReading... temperatureReading);
#Update
void update(TemperatureReading... temperatureReading);
#Delete
void delete(TemperatureReading temperatureReading);
}
Background service which saves to db
private void saveTempDatabase(float tmpMessageAsFloat, long tmpMessageDateTime) {
Log.d(TAG, "saveTempDatabase");
TemperatureReading tr = new TemperatureReading();
tr.setDateTime(tmpMessageDateTime);
tr.setReadingLocation("XXX"); //TODO
tr.setValue(tmpMessageAsFloat);
DatabaseSingleton.getAppDatabase(getApplicationContext()).temperatureReadingDao().insertAll(tr);
}
MainActivity were db is read from, uses Async task so it doesn't block UI
private void updateTemperature() {
Log.d(TAG, "updateTemperature");
new AsyncTask<Void, Void, Integer>() {
#Override
protected Integer doInBackground(Void... params) {
List<TemperatureReading> tr = DatabaseSingleton.getAppDatabase(MainActivity.this).temperatureReadingDao().getAll(); //List is always empty, no matter how many times I have called the saveTempDatabase() method in the service class.
return 0;
}
#Override
protected void onPostExecute(Integer agentsCount) {
}
}.execute();
}
Maybe it has to do with the context somehow?
EDIT:
Just tried adding .allowMainThreadQueries() when building the database and now it works. So for some reason my Async task isn't working?
Your AsyncTask seems to be wrong. You should return the list you would like to handle in doInBackground and then expect it in onPostExecute. Why do you always return 0?
This question already has answers here:
Why does Gson fromJson throw a JsonSyntaxException: Expected BEGIN_OBJECT but was BEGIN_ARRAY?
(2 answers)
Closed 5 years ago.
with the next problem, when trying to consume a webservice, then message and presentation;
Expected BEGIN_ARRAY but was BEGIN_OBJECT
I'm not sure how to make a scenario, I've already got data from a webservice, but when it's not a simple array.
I have tried many alternatives, but without success.
response api
{
"_links": {
"self": {
"href": "http://url.com/service?page=1"
},
"first": {
"href": "http://url.com/service"
},
"last": {
"href": "http://url.com/service?page=1"
}
},
"_embedded": {
"data": [
{
"id": 1,
"nome": "teste",
"_links": {
"self": {
"href": "http://url.com/service/1"
}
}
},
{
"id": 2,
"nome": "teste 2",
"_links": {
"self": {
"href": "http://url.com/service/2"
}
}
}
]
},
"page_count": 1,
"page_size": 25,
"total_items": 2,
"page": 1
}
Client
public class ApiClient {
private static final String BASE_URL = "http://url.com/";
private static Retrofit getClient() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
Gson gson = new GsonBuilder().setLenient().create();
return new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
}
/**
* Get API Service
*
* #return API Service
*/
public static ApiInterface getApiService() {
return getClient().create(ApiInterface.class);
}
}
Interface
/**
* Class ApiInterface
*/
public interface ApiInterface
{
#Headers("Accept: application/json")
#GET("/service")
Call<ArrayList<ServiceData>> getData();
}
Service
public class Service{
#SerializedName("data")
private ArrayList<ServiceData> service = new ArrayList<>();
}
Service Data
public class ServiceData {
#SerializedName("id")
private int id;
public ServiceData(int id, String nome) {
this.id = id;
}
public int getId() {
return id;
}
}
Activity
final Call<ArrayList<ServiceData>> service = apiService.getService();
service.enqueue(new Callback<ArrayList<ServiceData>>() {
#Override
public void onResponse(Call<ArrayList<ServiceData>> call, Response<ArrayList<ServiceData>> response) {
Log.e(TAG, "" + response.body());
}
#Override
public void onFailure(Call<ArrayList<ServiceData>> call, Throwable t) {
Log.e(TAG, "" + t);
}
});
You were in the right path but the response is the whole json and not only the data part you want.
I would create the ResponseApi class:
public class ResponseApi {
#SerializedName("_embedded")
private Service embedded;
}
And change on ApiInterface:
Call<ArrayList<ServiceData>> getData();
To:
Call<ResponseApi> getData();
Also in your activity replace all ArrayList<ServiceData> with ResponseApi.
With only this changes your code should work. And then you'll need to add getters in ResponseApi and Service to access the saved data.
UPDATE adding some getters:
We need the possibility to get the ArrayList of ServiceData of services:
public class Service {
// Your current code
public List<ServiceData> getServices() {
return service;
}
}
And also we could create a getter in ResponseApi to get embedded getEmbedded (I'll add the code as info only) but since we only want the services we could create a getter to the list of services getEmbededServices and use this last method.
public class ResponseApi {
// Your current code
public Service getEmbedded() { // Not used, only shown as info
return embedded;
}
public List<ServiceData> getEmbeddedServices() {
return embedded.getServices();
}
}
This way, when you'll receive a ResponseApi object in the onResponse method you can call its getEmbeddedServices to get the List of ServiceData and then you can loop through them to get the ids:
#Override
public void onResponse(Call<ResponseApi> call, Response<ResponseApi> response) {
Log.d(TAG, "services: " + response.getEmbeddedServices());
// Here you can loop the response.getEmbeddedServices() which is a List of ServiceData and get each of the ids. Ex:
for (ServiceData serviceData : response.getEmbeddedServices()) {
Log.d(TAG, "service Id: " + serviceData.getId());
// Here you have access to the ids and can do whatever you need with them.
}
}
By the way, only as a suggestion, I would rename (with refactor in Android Studio) this service var (in Service class):
private ArrayList<ServiceData> service = new ArrayList<>();
To servicesList:
private ArrayList<ServiceData> servicesList = new ArrayList<>();
And maybe also refactor the Service class to ServicesList class.
It's going to work either you rename them or not but, in my opinion, the code is more readable this way.
Try this
Your Parsing mapping has issues try below Model
ServiceData.java
public class ServiceData {
#SerializedName("_links")
#Expose
private Links links;
#SerializedName("_embedded")
#Expose
private Embedded embedded;
#SerializedName("page_count")
#Expose
private Integer pageCount;
#SerializedName("page_size")
#Expose
private Integer pageSize;
#SerializedName("total_items")
#Expose
private Integer totalItems;
#SerializedName("page")
#Expose
private Integer page;
public Links getLinks() {
return links;
}
public void setLinks(Links links) {
this.links = links;
}
public Embedded getEmbedded() {
return embedded;
}
public void setEmbedded(Embedded embedded) {
this.embedded = embedded;
}
public Integer getPageCount() {
return pageCount;
}
public void setPageCount(Integer pageCount) {
this.pageCount = pageCount;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Integer getTotalItems() {
return totalItems;
}
public void setTotalItems(Integer totalItems) {
this.totalItems = totalItems;
}
public Integer getPage() {
return page;
}
public void setPage(Integer page) {
this.page = page;
}
}
Self_.java
public class Self_ {
#SerializedName("href")
#Expose
private String href;
public String getHref() {
return href;
}
public void setHref(String href) {
this.href = href;
}
}
Self.java
public class Self {
#SerializedName("href")
#Expose
private String href;
public String getHref() {
return href;
}
public void setHref(String href) {
this.href = href;
}
}
Links_.java
public class Links_ {
#SerializedName("self")
#Expose
private Self_ self;
public Self_ getSelf() {
return self;
}
public void setSelf(Self_ self) {
this.self = self;
}
}
Links.java
public class Links {
#SerializedName("self")
#Expose
private Self self;
#SerializedName("first")
#Expose
private First first;
#SerializedName("last")
#Expose
private Last last;
public Self getSelf() {
return self;
}
public void setSelf(Self self) {
this.self = self;
}
public First getFirst() {
return first;
}
public void setFirst(First first) {
this.first = first;
}
public Last getLast() {
return last;
}
public void setLast(Last last) {
this.last = last;
}
}
Last.java
public class Last {
#SerializedName("href")
#Expose
private String href;
public String getHref() {
return href;
}
public void setHref(String href) {
this.href = href;
}
}
First.java
public class First {
#SerializedName("href")
#Expose
private String href;
public String getHref() {
return href;
}
public void setHref(String href) {
this.href = href;
}
}
Embedded.java
public class Embedded {
#SerializedName("data")
#Expose
private List<Datum> data = null;
public List<Datum> getData() {
return data;
}
public void setData(List<Datum> data) {
this.data = data;
}
}
Datum.java
public class Datum {
#SerializedName("id")
#Expose
private Integer id;
#SerializedName("nome")
#Expose
private String nome;
#SerializedName("_links")
#Expose
private Links_ links;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public Links_ getLinks() {
return links;
}
public void setLinks(Links_ links) {
this.links = links;
}
}
Try to remove ArrayList from every where and direct use ServiceData
Interface
/**
* Class ApiInterface
*/
public interface ApiInterface
{
#Headers("Accept: application/json")
#GET("/service")
Call<ServiceData> getData();
}
Service Data
public class ServiceData {
#SerializedName("id")
private int id;
public ServiceData(int id, String nome) {
this.id = id;
}
public int getId() {
return id;
}
}
Activity
final Call<ServiceData> service = apiService.getService();
service.enqueue(new Callback<ServiceData>() {
#Override
public void onResponse(Call<ServiceData> call, Response<ServiceData> response) {
Log.e(TAG, "" + response.body());
}
#Override
public void onFailure(Call<ServiceData> call, Throwable t) {
Log.e(TAG, "" + t);
}
});
You call and waiting for List. Call<ArrayList<ServiceData>>
But in the response, you have an object.
[...] - is array (list)
{...} - is object
You need to create classes for all parameters properly.
Just try to look at this service (or similar):
http://www.jsonschema2pojo.org/
Or Android Studio (IDEA) also has a plugin (GsonFormat) for converting JSON.