Объедините комнату и Retroffit с Dagger2
Как правильно создать DAO с помощью Room and Retrofit?
У меня есть модуль базы данных, как это:
@Module
public class ApplicationDatabaseModule {
private final String mDatabaseName;
ApplicationDatabase mApplicationDatabase;
public ApplicationDatabaseModule(@ApplicationContext Context context, Class<? extends ApplicationDatabase> roomDataBaseClass, String databaseName) {
mDatabaseName = databaseName;
mApplicationDatabase = Room.databaseBuilder(context, roomDataBaseClass, mDatabaseName).build();
}
@Singleton
@Provides
ApplicationDatabase provideApplicationDatabase() {
return mApplicationDatabase;
}
@Singleton
@Provides
CitiesDao provideCitiesDao() {
return mApplicationDatabase.getCitiesDao();
}
}
Класс POJO, как это:
@Entity
public class City {
@PrimaryKey
@ColumnInfo(name = "id")
private int cityId;
@ColumnInfo(name = "name")
private String cityName;
public int getCityId() {
return cityId;
}
public void setCityId(int cityId) {
this.cityId = cityId;
}
public String getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
@Override
public String toString() {
return "City [cityId = " + cityId + ", cityName = " + cityName + "]";
}
}
Интерфейс DAO, как это:
@Dao
public interface CitiesDao {
@Insert
void insertCities(City... cities);
@Query("SELECT * FROM City")
City[] queryCities();
}
И API для модернизации:
public interface CitiesApi {
@GET("/api/cities")
Call<City[]> requestCities();
}
Как я знаю, DAO отвечает за доступ к данным, в том числе к данным, передаваемым через REST-клиент. Но эти две части представлены интерфейсами и встроены в отдельные классы. Как правильно внедрить DAO?
2 ответа
DAO отвечает за доступ к данным
да
В том числе данные передаются через REST-клиент.
Бог нет
Как правильно внедрить DAO?
Room уже генерирует правильный способ реализации вашего DAO на основе вашего интерфейса + аннотации, я думаю, это называется CitiesDao_Impl
,
Как правильно создать DAO с помощью Room and Retrofit?
Комната не знает о модернизации и не должна знать о модернизации. Он заботится только о сохранении локальных данных.
То есть ваш DAO должен выглядеть так:
@Dao
public interface CitiesDao {
@Insert
@Transaction
void insertCities(City... cities);
@Query("SELECT * FROM City")
LiveData<List<City>> queryCities();
}
Так что вам действительно нужен работник, который будет извлекать новые данные в фоновом режиме, когда кеш недействителен (принудительно извлекает новые данные) или когда должна запускаться ваша задача синхронизации (например, когда устройство заряжается, вы подключены к WIFI и находитесь в С 2 до 7 утра - для этого вам понадобится WorkManager
).
Немедленно получить новые данные, хотя это довольно просто, все, что вам нужно, это либо AsyncTask в одноэлементном контексте, который возвращает null
от doInBackground
или ваш собственный Исполнитель, которому вы отправляете фоновое задание.
public class FetchCityTask extends AsyncTask<Void, Void, Void> {
...
@Override
protected Void doInBackground(Void... params) {
List<City> cities = citiesApi.requestCities().execute().body(); // TODO error handling
citiesDao.insertCities(cities);
return null;
}
}
А потом
new FetchCityTask(...).execute();
Теперь, когда эта задача выполняется, ваш пользовательский интерфейс будет обновляться с использованием последних данных, наблюдая за данными LiveData, которые вы храните в ViewModel.
public class CitiesViewModel
extends ViewModel {
private final CitiesDao citiesDao;
private LiveData<List<City>> liveResults;
public CitiesViewModel(...) {
...
liveResults = citiesDao.queryCities();
}
public LiveData<List<City>> getCities() {
return liveResults;
}
}
А также
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
recyclerView = view.findViewById(R.id.recycler_view);
CitiesViewModel viewModel = ViewModelProviders.of(this).get(CitiesViewModel.class, ...);
...
viewModel.getTasks().observe(getViewLifecycle(), list -> {
//noinspection Convert2MethodRef
listAdapter.submitList(list);
});
}
Вы хотите создать класс репозитория для обработки ваших данных. Тогда вы просто взаимодействуете со своим хранилищем. Какой-то псевдокод для вас:
class Repository {
private CitiesDao localSource;
private CitiesApi remoteSource;
public Repository() {
//initialize objects here
}
City[] getCities() {
if (networkIsAvailable) {
City[] cities = remoteSource.requestCities();
saveCitiesToDatabase(cities);
return cities;
} else {
return localSource.queryCities();
}
}
private void saveCitiesToDatabase(City[] cities) {
//TODO save cities to databse
}
}