问题
I am trying to implement new architecture (MVVM + RxJava2 + Dagger2 + Retrofit) in my existing project. I have set up whole above architecture and tested on HomeActivity. Dependencies injected in HomeViewModel. So Now I was trying to inject dependencies same as HomeViewModel in a FollowingViewModel of FollowingFragment which is a container Fragment of HomeActivity.But injected dependencies always return null(Not Initiziling). I am following this project riggaroo/android-arch-components-date-countdown to Inject dependencies but in this sample, only activities are used no fragment. So I don't know what is happening and who to inject deps in multiple ViewModels.
Here is code for some Important classes to understand:
AppApplication.class
public class AppApplication extends MultiDexApplication implements HasActivityInjector {
@Inject
DispatchingAndroidInjector<Activity> dispatchingAndroidInjector;
@Override
public void onCreate() {
...........................
AppInjector.init(this)
..........................
}
@Override
public AndroidInjector<Activity> activityInjector() {
return dispatchingAndroidInjector;
}
}
AppInjector.class
public class AppInjector {
private AppInjector() {
}
public static void init(AppApplication appApplication) {
DaggerAppComponent.builder()
.application(appApplication)
.build()
.inject(appApplication);
appApplication
.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
handleActivity(activity);
}
});
}
private static void handleActivity(Activity activity) {
if (activity instanceof HasSupportFragmentInjector) {
AndroidInjection.inject(activity);
}
if (activity instanceof FragmentActivity) {
((FragmentActivity) activity).getSupportFragmentManager()
.registerFragmentLifecycleCallbacks(
new FragmentManager.FragmentLifecycleCallbacks() {
@Override
public void onFragmentCreated(FragmentManager fm, Fragment f,
Bundle savedInstanceState) {
if (f instanceof Injectable) {
AndroidSupportInjection.inject(f);
}
}
}, true);
}
}
}
AppComponent.class
@Singleton
@Component(modules = {AndroidSupportInjectionModule.class,ActivityBuilderModule.class, AppModule.class, NetworkModule.class})
public interface AppComponent {
@Component.Builder
interface Builder {
@BindsInstance
Builder application(AppApplication application);
AppComponent build();
}
void inject(AppApplication app);
AppModule.class
@Module(includes = { ViewModelModule.class})
public class AppModule {
@Provides
Context provideContext(AppApplication application) {
return application.getApplicationContext();
}
}
ActivityBuilderModule.class
@Module
public abstract class ActivityBuilderModule {
@ContributesAndroidInjector(modules = FragmentBuildersModule.class)
abstract HomeActivity bindHomeActivity();
}
FragmentBuildersModule.class
@Module
public abstract class FragmentBuildersModule {
@ContributesAndroidInjector
abstract FollowingListFragment contributeFollowingListFragment();
}
ViewModule.class
@Module
public abstract class ViewModelModule {
@Binds
@IntoMap
@ViewModelKey(FollowingViewModel.class)
abstract ViewModel bindFollowingViewModel(FollowingViewModel followingViewModel);
@Binds
@IntoMap
@ViewModelKey(HomeViewModel.class)
abstract ViewModel bindHomeViewModel(HomeViewModel homeViewModel);
@Binds
abstract ViewModelProvider.Factory bindViewModelFactory(MyViewModelFactory factory);
}
NetworkModule.class
@Module
public class NetworkModule {
public NetworkModule(){}
@Provides
@Singleton
CompositeDisposable getCompositeDisposable() {
return new CompositeDisposable();
}
@Provides
@Singleton
Retrofit provideCall() {
// OKHttps and Retrofit code...
}
@Provides
@Singleton
@SuppressWarnings("unused")
public ApiCallInterface providesNetworkService(
Retrofit retrofit) {
return retrofit.create(ApiCallInterface.class);
}
@Provides
@Singleton
@SuppressWarnings("unused")
public Repository providesService(
ApiCallInterface networkService) {
return new Repository(networkService);
}
}
MyViewModelFactory.class
@Singleton
public class MyViewModelFactory extends ViewModelProvider.NewInstanceFactory {
private final Map<Class<? extends ViewModel>, Provider<ViewModel>> creators;
@Inject
public MyViewModelFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> creators) {
this.creators = creators;
}
@SuppressWarnings("unchecked")
@Override
public <T extends ViewModel> T create(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("unknown model class " + modelClass);
}
try {
return (T) creator.get();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
This class is used to create Instances of all viewModels. I have debugged and found only HomeViewModel instance is creating.
Now I have created HomeViewModel which is called from HomeActivity. Which is working fine. Now same implementaion is done in FollowingFragment but doesn't work. Let me show you how I have initialized FollowViewModel from FollowingListFragment.class
public class FollowingListFragment extends BaseFragment implementsInjectable {
@Inject
MyViewModelFactory myViewModelFactory;
private FollowingViewModel followingViewModel;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = getActivity();
followingViewModel = ViewModelProviders.of(this, plownsViewModelFactory)
.get(FollowingViewModel.class);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_following_list, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
followingViewModel.getFollowings(id,curser);
}
}
Here is FollowingViewModel.class
public class FollowingViewModel extends ViewModel {
@Inject
Repository service;
@Inject
CompositeDisposable subscriptions;
@Inject
public FollowingViewModel() {
}
/*void setService(Repository service){
this.service = service;
}*/
void getFollowings(String id,String curser) {
if(service!=null) { **//HERE SERVICE RETURNS NULL**
Disposable subscription = service.getFollowings(id, curser, new IResponseCallback<FollowingResponse.FollowingResult>() {
@Override
public void onSuccess(FollowingResponse.FollowingResult followingResult) {
}
@Override
public void onError(Throwable throwable) {
}
});
subscriptions.add(subscription);
}else {
Log.d("FollowViewModel", "Service is null " );
}
}
Here is HomeActivity and HomeViewModel class code which is working fine. HomeActivity.class
public class HomeActivity extends BaseActivity implements HasSupportFragmentInjector, Injectable {
@Inject
DispatchingAndroidInjector<Fragment> supportFragmentInjector;
@Inject
MyViewModelFactory viewFactory;
HomeViewModel homeViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
homeViewModel = ViewModelProviders.of(this,viewFactory).get(HomeViewModel.class);
homeViewModel.getFollowings("xyx",null);
}
@Override
public AndroidInjector<Fragment> supportFragmentInjector() {
return supportFragmentInjector;
}
}
HomeViewModel.class
public class HomeViewModel extends ViewModel {
@Inject
Repository service;
@Inject
CompositeDisposable subscriptions;
@Inject
public HomeViewModel() {
}
void getFollowings(String id,String curser) {
if(service!=null) { **// Returing null service**
}
}else {
Log.d("FollowViewModel", "Service is null " );
}
}
}
I am struggling for 2 days. Please help, suggest. Thanks. Please don't downvote if you are not willing to help.
来源:https://stackoverflow.com/questions/50266178/how-to-inject-dependencies-in-viewmodels-using-dagger2