Reputation: 719
I have to convert the list of objects to the Event object and vice versa. I need it for the Room Database to store data from web. I created two converters, but they don't work. Converters class is set in database, data from web works well, I can download one object from the list, so there is no problem with an api and database.
Converters:
public class Converters {
@TypeConverter
public static ArrayList<Event> fromEvent(String event) {
Type listType = new TypeToken<ArrayList>() {}.getType();
return new Gson().fromJson(event, listType);
}
@TypeConverter
public static String fromList(ArrayList<Event> events) {
Gson gson = new Gson();
String json = gson.toJson(events);
return json;
}
}
Fragment:
private void getEvents() {
eventsViewModel.getEvents().observe(getViewLifecycleOwner(), new Observer<Event>() {
@Override
public void onChanged(Event events) {
if (events == null) {
Log.e(TAG, "EVENTS NULL");
}
else {
Log.e(TAG, "EVENTS OK");
}
List<Event> events1 = (List) events;
adapter.setEvents(events1);
adapter.notifyDataSetChanged();
}
});
}
I am trying here parse Object events to the Event list but there is an error: java.lang.ClassCastException: com.example.data.model.Event cannot be cast to java.util.List
Maybe I can't convert an object itself and I have to create another POJO and then put Event POJO to them as a list?
Repository:
public class EventRepository {
private final EventsApi apiInterface;
private EventDao eventDao;
@Inject
public EventRepository(EventsApi apiInterface, EventDao eventDao) {
this.apiInterface = apiInterface;
this.eventDao = eventDao;
}
public LiveData<ArrayList<Event>> fetchEvents() {
final MutableLiveData<ArrayList<Event>> data = new MutableLiveData<>();
apiInterface.getEvents().enqueue(new Callback<ArrayList<Event>>() {
@Override
public void onResponse(Call<ArrayList<Event>> call, Response<ArrayList<Event>> response) {
data.setValue(response.body());
persistFetchedEvents(response.body());
}
@Override
public void onFailure(Call<ArrayList<Event>> call, Throwable t) {
data.setValue(null);
}
});
return data;
}
public LiveData<List<Event>> getEvents() {
initEvents();
return eventDao.getEvents();
}
private void persistFetchedEvents(List<Event> events) {
new InsertEventsAsyncTask(eventDao).execute(events);
}
private static class InsertEventsAsyncTask extends AsyncTask<List<Event>, Void, Void> {
private EventDao eventDao;
private InsertEventsAsyncTask(EventDao eventDao) {
this.eventDao = eventDao;
}
@SafeVarargs
@Override
protected final Void doInBackground(List<Event>... events) {
eventDao.insertAll(events);
return null;
}
}
private void initEvents() {
if (isFetchEventsNeeded(ZonedDateTime.now().minusHours(1))) {
fetchEvents();
}
}
private Boolean isFetchEventsNeeded(ZonedDateTime lastfetchTime) {
ZonedDateTime thirtyMinutesAgo = ZonedDateTime.now().minusMinutes(30);
return lastfetchTime.isBefore(thirtyMinutesAgo);
}
}
Dao:
@Dao
public interface EventDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void updateEvent(Event event);
@Query("SELECT * FROM events WHERE idKey = 0")
LiveData<Event> getEvents();
}
Event:
@Entity(tableName = "events")
@TypeConverters(Converters.class) public class Event {
@SerializedName("id")
@Expose
private int id;
@SerializedName("title")
@Expose
private String title;
@SerializedName("subtitle")
@Expose
private String subtitle;
@SerializedName("date")
@Expose
private String date;
@SerializedName("imageUrl")
@Expose
private String imageUrl;
@SerializedName("videoUrl")
@Expose
private String videoUrl;
@PrimaryKey(autoGenerate = false)
private int idKey = 0;
public Event(int id, String title, String subtitle, String date, String imageUrl, String videoUrl) {
this.id = id;
this.title = title;
this.subtitle = subtitle;
this.date = date;
this.imageUrl = imageUrl;
this.videoUrl = videoUrl;
}
public int getIdKey() {
return idKey;
}
public void setIdKey(int idKey) {
this.idKey = idKey;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getSubtitle() {
return subtitle;
}
public void setSubtitle(String subtitle) {
this.subtitle = subtitle;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public String getVideoUrl() {
return videoUrl;
}
public void setVideoUrl(String videoUrl) {
this.videoUrl = videoUrl;
}
}
Upvotes: 0
Views: 366
Reputation: 2212
java.lang.ClassCastException
is being thrown because you are trying to cast an Event
object into a list. Make sure your eventsViewModel.getEvents()
returns LiveData<ArrayList<Event>>
instead of LiveData<Event>
.
Change the return type of getEvents()
in EventDao
from LiveData<Event>
to LiveData<ArrayList<Event>>
@Query("SELECT * FROM events WHERE idKey = 0")
LiveData<ArrayList<Event>> getEvents();
Also your call to your ApiInterface returns a single event. Make sure it returns a list of Events
. Then you can persist them all and your LiveData<ArrayList<Event>>
from eventDao.getEvents()
will update with your newly persisted list of Event
objects.
EDIT Per your request I'm adding an example
In your fragment
private void getEvents() {
eventsViewModel.getEvents().observe(getViewLifecycleOwner(), new Observer<List<Event>>() {
@Override
public void onChanged(List<Event> events) {
if (events == null) {
Log.e(TAG, "EVENTS NULL");
}
else {
Log.e(TAG, "EVENTS OK");
}
adapter.setEvents(events);
adapter.notifyDataSetChanged();
}
});
}
In the Repository
public class EventRepository {
private final EventsApi apiInterface;
private EventDao eventDao;
@Inject
public EventRepository(EventsApi apiInterface, EventDao eventDao) {
this.apiInterface = apiInterface;
this.eventDao = eventDao;
}
public LiveData<ArrayList<Event>> fetchEvents() {
final MutableLiveData<ArrayList<Event>> data = new MutableLiveData<>();
apiInterface.getEvents().enqueue(new Callback<ArrayList<Event>>() {
@Override
public void onResponse(Call<ArrayList<Event>> call, Response<ArrayList<Event>> response) {
data.postValue(response.body());
persistFetchedEvents(response.body());
}
@Override
public void onFailure(Call<ArrayList<Event>> call, Throwable t) {
}
});
return data;
}
public LiveData<List<Event>> getEvents() {
initEvents();
return eventDao.getEvents();
}
private void persistFetchedEvents(List<Event> events) {
new InsertEventsAsyncTask(eventDao).execute(events);
}
private static class InsertEventsAsyncTask extends AsyncTask<List<Event>, Void, Void> {
private EventDao eventDao;
private InsertEventsAsyncTask(EventDao eventDao) {
this.eventDao = eventDao;
}
@Override
protected Void doInBackground(List<Event>... events) {
Event[] eventArray = events[0].toArray(new Event[events[0].size()]);
eventDao.insertAll(eventArray);
return null;
}
}
private void initEvents() {
if (isFetchEventsNeeded(ZonedDateTime.now().minusHours(1))) {
fetchEvents();
}
}
private Boolean isFetchEventsNeeded(ZonedDateTime lastfetchTime) {
ZonedDateTime thirtyMinutesAgo = ZonedDateTime.now().minusMinutes(30);
return lastfetchTime.isBefore(thirtyMinutesAgo);
}
}
In your dao(I added a new method to insertAll)
@Dao
public interface EventDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertAll(Event... events);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void updateEvent(Event event);
@Query("SELECT * FROM events")
LiveData<List<Event>> getEvents();
}
You will need to change the return type of eventsViewModel.getEvents()
to LiveData<List<Event>>
and apiInterface.getEvents()
to Call<ArrayList<Event>>
Upvotes: 2