Я должен преобразовать список объектов в объект и наоборот в комнате базы данных - PullRequest
0 голосов
/ 31 октября 2019

Мне нужно преобразовать список объектов в объект Event и наоборот. Мне нужно это для базы данных комнат для хранения данных из Интернета. Я создал два конвертера, но они не работают. Класс конвертеров установлен в базе данных, данные из Интернета работают хорошо, я могу загрузить один объект из списка, поэтому нет проблем с API и базой данных.

Конвертеры:

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;
}
}

Фрагмент:

 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();
        }
    });
}

Я пытаюсь проанализировать события объекта в списке событий, но есть ошибка: java.lang.ClassCastException: com.example.data.model.Event не может быть приведен к java.util. .List

Может быть, я не могу преобразовать сам объект, и мне нужно создать еще один POJO, а затем поместить в него Event POJO в виде списка?

Репозиторий:

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();
}

Событие:

@Entity(tableName = "events")

@ TypeConverters (Converters.class) открытый класс Событие {

@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;
}
}

1 Ответ

2 голосов
/ 01 ноября 2019

java.lang.ClassCastException выбрасывается, потому что вы пытаетесь преобразовать объект Event в список. Убедитесь, что ваш eventsViewModel.getEvents() возвращает LiveData<ArrayList<Event>> вместо LiveData<Event>.

Измените тип возврата getEvents() в EventDao с LiveData<Event> на LiveData<ArrayList<Event>>

@Query("SELECT * FROM events WHERE idKey = 0")
LiveData<ArrayList<Event>> getEvents();

Также ваш звонок на ваш ApiInterface возвращает одно событие. Убедитесь, что он возвращает список Events. Затем вы можете сохранить их все, и ваш LiveData<ArrayList<Event>> из eventDao.getEvents() обновится с вашим недавно сохраненным списком Event объектов.

EDIT По вашему запросу я добавляю пример

В вашем фрагменте

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();
        }
    });
}

В репозитории

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);
}

}

В вашем дао (я добавил новый метод для вставки всего)

@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();
}

Вам нужно будет изменить тип возврата с eventsViewModel.getEvents() на LiveData<List<Event>> и apiInterface.getEvents() на Call<ArrayList<Event>>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...