如果没有阅读Part1和Part2请先阅读
注入带构造函数的ViewModel
在初始化一个带参数的ViewModel,需要使用ViewModelProvider.Factory的实例进行初始化,如果将一个ViewModelFactory用在不同的ViewModel上,ViewModelFactory需要对各种不同的参数进行处理。
在本项目中使用线程池对插入和读取数据的线程进行管理;使用UserRepo对User的插入和读取进行管理。
在Dagger2中有 Multibindings为对象创建一个Map:
- Key:表示ViewModel的类型,在本项目中表示为
MainFragmentViewModel::class - Vaule:表示ViewModel的实例
Dagger2在编译的时候会创建Map,我们将该Map以参数的形式传入到ViewModelFactory中,当我们调用create()方法时,将会从map中取出正确的实例。
AppExecutors创建
使用Javax包中@Singleton注解,表示其为单例模式;对于自定义类直接在构造函数AppExecutors()上添加注解@Inject,可以直接进行注入,无需在Module中提供providers
@Singleton
public class AppExecutors {
private final Executor diskIO;
public AppExecutors(Executor diskIO){
this.diskIO=diskIO;
}
@Inject
public AppExecutors(){
this(Executors.newSingleThreadExecutor());
}
public Executor getDiskIO() {
return diskIO;
}
}
UserRepo 创建
直接在构造函数添加@Inject进行注入
@Singleton
public class UserRepo {
private final UserDb userDb;
private final UserDao userDao;
private final AppExecutors appExecutors;
@Inject
public UserRepo(UserDb userDb,UserDao userDao,AppExecutors appExecutors){
this.userDb=userDb;
this.userDao=userDao;
this.appExecutors=appExecutors;
}
public void insertUser(final User user){
appExecutors.getDiskIO().execute(new Runnable() {
@Override
public void run() {
userDao.insert(user);
}
});
}
public void readUser(){
appExecutors.getDiskIO().execute(new Runnable() {
@Override
public void run() {
int m =userDao.getUsers().size();
Log.i("+++","++++"+m);
}
});
}
}
ViewModelFactory创建
@Singleton
public class ViewModelFactory implements ViewModelProvider.Factory {
private final Map<Class<? extends ViewModel>, Provider<ViewModel>> creators;
@Inject
public ViewModelFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> creators) {
this.creators = creators;
}
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
Provider<? extends ViewModel> creator = creators.get(modelClass);
if (creator == null) {
for (Map.Entry<Class<? extends ViewModel>, Provider<ViewModel>> entry : creators.entrySet()) {
if (modelClass.isAssignableFrom(entry.getKey())) {
creator = entry.getValue();
break;
}
}
}
if (creator == null) {
throw new IllegalArgumentException("未知类" + modelClass);
}
try {
return (T)creator.get();
}catch (Exception e){
throw new RuntimeException(e);
}
// return null;
}
}
ViewModelModule创建
创建ViewModelModule并使用@Binds注解提供注入
@Module
public abstract class ViewModelModule {
@Binds
abstract ViewModelProvider.Factory bindViewModelFactory(ViewModelFactory factory);
}
ViewModelKey创建
创建需要进行多重绑定的Map,并绑定ViewModel
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@MapKey
public @interface ViewModelKey {
Class<? extends ViewModel> value();
}
在ViewModelModule中添加需要注入的ViewModel
通过@Binds @IntoMap @ViewModelKey 注解,提供给前文创建的Map数据,Key为 MainFragmentViewModel.class value为MainFragmentViewModel 实例
@Module
public abstract class ViewModelModule {
@Binds
@IntoMap
@ViewModelKey(MainFragmentViewModel.class)
abstract ViewModel bindViewModel(MainFragmentViewModel detailViewModel);
}
在AppMoudle中添加ViewModelModule
@Module(includes = {DbModule.class,ViewModelModule.class})
public class AppModule {
}
修改MainFragment
public class MainFragment extends DaggerFragment
@Inject
ViewModelProvider.Factory viewModelFactory;
private MainFragmentViewModel mainFragmentViewModel;
//用于获取DetailFragment实例
FragmentDetailBinding fragmentDetailBinding;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
AndroidSupportInjection.inject(this);
fragmentDetailBinding = DataBindingUtil
.inflate(inflater, R.layout.fragment_detail, container, false);
fragmentDetailBinding.insertDateTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mainFragmentViewModel.insertUser();
}
});
fragmentDetailBinding.readDataTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mainFragmentViewModel.readUser();
}
});
return fragmentDetailBinding.getRoot();
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mainFragmentViewModel = ViewModelProviders.of(this, viewModelFactory).get(MainFragmentViewModel.class);
}
}