使用 Dagger2 组合 Room 和 Retroffit
Combine Room and Retroffit with Dagger2
使用 Room 和 Retrofit 创建 DAO 的正确方法是什么?
我有这样的数据库模块:
@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 class 像这样:
@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 客户端传递的数据。但这两个部分由接口表示,并内置在单独的 classes 中。实现 DAO 的正确方法是什么?
您想创建一个存储库 class 来处理您的数据。然后您只需与您的存储库进行交互。一些伪代码给你:
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
}
}
DAO is responsible for accessing data
是
, including data passed through REST-client.
上帝没有
What is the proper way to implement DAO?
Room 已经根据您的接口 + 注释为您的 DAO 生成了正确的实现方式,我认为它叫做 CitiesDao_Impl
。
What the proper way to create DAO with Room and Retrofit?
Room 不知道 Retrofit,也不应该知道 Retrofit。它只关心本地数据持久化。
意味着您的 DAO 需要如下所示:
@Dao
public interface CitiesDao {
@Insert
@Transaction
void insertCities(City... cities);
@Query("SELECT * FROM City")
LiveData<List<City>> queryCities();
}
所以你实际上需要的是一个 Worker,当缓存无效(强制获取新数据)或你的同步任务应该 运行(例如,当设备正在充电并且您正在使用 WIFI 并且您处于凌晨 2 点到早上 7 点时 - 为此您需要 WorkManager
)。
虽然立即获取新数据相当容易,但您所需要的只是 returns null
来自 doInBackground
的单例上下文中的 AsyncTask,或者您自己的 Executor post你的后台任务。
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();
现在,当此任务 运行 时,您的 UI 将通过观察存储在 ViewModel 中的 LiveData 使用最新数据进行更新。
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);
});
}
使用 Room 和 Retrofit 创建 DAO 的正确方法是什么?
我有这样的数据库模块:
@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 class 像这样:
@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 客户端传递的数据。但这两个部分由接口表示,并内置在单独的 classes 中。实现 DAO 的正确方法是什么?
您想创建一个存储库 class 来处理您的数据。然后您只需与您的存储库进行交互。一些伪代码给你:
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
}
}
DAO is responsible for accessing data
是
, including data passed through REST-client.
上帝没有
What is the proper way to implement DAO?
Room 已经根据您的接口 + 注释为您的 DAO 生成了正确的实现方式,我认为它叫做 CitiesDao_Impl
。
What the proper way to create DAO with Room and Retrofit?
Room 不知道 Retrofit,也不应该知道 Retrofit。它只关心本地数据持久化。
意味着您的 DAO 需要如下所示:
@Dao
public interface CitiesDao {
@Insert
@Transaction
void insertCities(City... cities);
@Query("SELECT * FROM City")
LiveData<List<City>> queryCities();
}
所以你实际上需要的是一个 Worker,当缓存无效(强制获取新数据)或你的同步任务应该 运行(例如,当设备正在充电并且您正在使用 WIFI 并且您处于凌晨 2 点到早上 7 点时 - 为此您需要 WorkManager
)。
虽然立即获取新数据相当容易,但您所需要的只是 returns null
来自 doInBackground
的单例上下文中的 AsyncTask,或者您自己的 Executor post你的后台任务。
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();
现在,当此任务 运行 时,您的 UI 将通过观察存储在 ViewModel 中的 LiveData 使用最新数据进行更新。
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);
});
}