MVVM-DataSource
2019-11-18 本文已影响0人
tea也么
简介
熟悉谷歌arch框架的同学都知道,arch中mvvm思想主要依靠LiveData来作为数据源驱动界面,这里的DataSource提供了request和response两个LiveData,response用于驱动界面改变,request用于设置请求参数。
数据请求和响应实现了分离:
// old
getCall(request, response->{
view.onChange();
})
// now
// 界面只需要设置一个唯一数据源
response().observer(this,response->{
view.onChange();
})
// 数据请求可以设置在任何地方
click1(v->{
request().setValue(request1);
})
click2(v->{
request().setValue(request2);
})
DataSorece全局唯一性:
每一个DataSorece全局单例,所有的界面都依赖同一个数据源,也就不再会出现数据不同步的问题了,从而达到牵一发动全身的效果。DataSorece实现了如同EventBus的效果,但又优于EventBus,因为避免了EventBus的不易追溯和缺乏 Lifecycle 的加持等缺点。
使用介绍
- 根据所需实现DataSource,下面有具体介绍
- 在ViewModel中通过@Source声明DataSource,ViewModel需要继承BaseViewModel
public class ArchViewModel extends BaseViewModel {
@Source
public WeatherRetrofitSource mRetrofitSource;
public ArchViewModel(@NonNull Application application) {
super(application);
}
}
- 在ViewController中使用
- 获取响应数据,驱动UI
mRetrofitSource.response().observe(getViewLifecycleOwner(), rp -> {
mBinding.weather2.setText(rp.data.weather);
});
- 发起请求
mRetrofitSource.request().setValue("天津");
- 重新加载,会根据上一次的的请求参数再次请求数据
mRetrofitSource.onReload(null);
常用的DataSource
- IRetrofitDataSource
- IRoomDataSource
- IRetrofitAndRoomDataSource
IRetrofitDataSource只访问网络,IRoomDataSource只访问数据库,IRetrofitAndRoomDataSource访问网络和数据库
IRetrofitDataSource
public class WeatherSource extends IRetrofitDataSource<String, CurWeather> {
@NonNull
@Override
public Call<CurWeather> getCall(String city) {
return WebService.getInstance().getWeather(city);
}
}
public interface IWebService {
@GET("http://www.mxnzp.com/api/weather/current/{city}")
Call<CurWeather> getWeather(@Path("city") String city);
}
在WebService中配置好网络访问的接口,然后直接实现IRetrofitDataSource的getCall的方法即可
IRoomDataSource
public class WeatherRoomSource extends IRoomDataSource<String, WeatherEntity> {
private WeatherDao mDao;
public WeatherRoomSource(@NonNull Application application) {
super(application);
mDao = DBManager.getInstance(mApplication).mDatabase.mWeatherDao();
}
@NonNull
@Override
public LiveData<WeatherEntity> query(@Nullable String param) {
return mDao.query(param);
}
@Override
public void insert(@NonNull WeatherEntity weatherEntity) {
mDao.insert(weatherEntity);
}
@Override
public void delete(@NonNull WeatherEntity weatherEntity) {
mDao.delete(weatherEntity);
}
@Override
public void update(@NonNull WeatherEntity weatherEntity) {
mDao.update(weatherEntity);
}
}
@Dao
public interface WeatherDao {
@Query("select * from weatherentity where address=:address")
LiveData<WeatherEntity> query(String address);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(WeatherEntity... entity);
@Delete
void delete(WeatherEntity... entity);
@Update
void update(WeatherEntity entity);
}
RoomSource需要实现增删改查四个接口
IRetrofitAndRoomDataSource
public class WeatherMixDataSource extends IRetrofitAndRoomDataSource<String, CurWeather,
WeatherEntity> {
private WeatherDao mDao;
public WeatherMixDataSource(@NonNull Application application) {
super(application);
mDao = DBManager.getInstance(mApplication).mDatabase.mWeatherDao();
}
@NonNull
@Override
public Call<CurWeather> getCall(@Nullable String request) {
return WebService.getInstance().getWeather(request);
}
@Override
protected boolean isUpdateFromNet(@Nullable String request) {
return true;
}
@NonNull
@Override
protected WeatherEntity transformNetToDbData(@NonNull CurWeather netData) {
...
...
return entity;
}
@NonNull
@Override
public LiveData<WeatherEntity> query(@Nullable String param) {
return mDao.query(param);
}
@Override
public void insert(@NonNull WeatherEntity entity) {
mDao.insert(entity);
}
@Override
public void delete(@NonNull WeatherEntity entity) {
mDao.delete(entity);
}
@Override
public void update(@NonNull WeatherEntity entity) {
mDao.update(entity);
}
}
IRetrofitAndRoomDataSource的实现原理就是每次查询会首先访问数据库数据,然后根据isUpdateFromNet方法判断是否访问网络更新最新数据,如果更新则会同步到数据库中,并把数据反馈到界面上
IRetrofitAndRoomDataSource除了要实现网络接口和数据库增删改查的接口,还需要实现isUpdateFromNet和transformNetToDbData方法
- isUpdateFromNet
判断是否从网络更新数据到数据库,这个地方可以设置一个时间段来做更新数据的依据,从而避免频繁访问网络相同资源,造成资源浪费 - transformNetToDbData
由于网络数据和数据库数据的属性可能存在差异性,所以需要通过该接口进行转换