Я делаю небольшое приложение для Android в MVVM и Dagger 2. Но я не знаю, как правильно использовать Dagger 2 в случае, когда у меня есть одно действие и два фрагмента. Оба фрагмента являются владельцами моделей ViewModels. Я вставил ViewModelProvider в Fragment, но я все еще не уверен в этом решении. Может, кто-нибудь улучшит мой код?
Активность :
public class MainActivity extends DaggerAppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView navView = findViewById(R.id.nav_view);
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupWithNavController(navView, navController);
}
}
Первый фрагмент :
public class EventsFragment extends DaggerFragment {
private static final String TAG = "EventsFragment";
private EventsViewModel eventsViewModel;
private final EventsAdapter adapter = new EventsAdapter();
private List<Event> events = new ArrayList<>();
@Inject
ViewModelProviderFactory viewModelProviderFactory;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
eventsViewModel = ViewModelProviders.of(this, viewModelProviderFactory).get(EventsViewModel.class);
View root = inflater.inflate(R.layout.fragment_events, container, false);
RecyclerView recyclerView = root.findViewById(R.id.events_recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(adapter);
getEvents();
return root;
}
Второй фрагмент:
public class ScheduleFragment extends DaggerFragment {
private ScheduleViewModel scheduleViewModel;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
scheduleViewModel = ViewModelProviders.of(this).get(ScheduleViewModel.class);
View root = inflater.inflate(R.layout.fragment_schedule, container, false);
return root;
}
@Override
public void onAttach(Context context) {
AndroidSupportInjection.inject(this);
super.onAttach(context);
}
}
В этом случае оба фрагмента работают, но я могу внедрить ViewModelFactory только в один. Если я добавлю это ко второму: error: не могу найти класс символов DaggerAppComponent
ActivityBuildersModule:
@Module
public abstract class ActivityBuildersModule {
@ContributesAndroidInjector(modules = FragmentBuildersModule.class)
abstract MainActivity contributeMainActivity();
}
AppComponent:
@Singleton
@Component(
modules = {
AndroidSupportInjectionModule.class,
ActivityBuildersModule.class,
AppModule.class,
ViewModelFactoryModule.class
}
)
public interface AppComponent extends AndroidInjector<BaseApplication> {
@Component.Builder
interface Builder {
@BindsInstance
Builder application(Application application);
AppComponent build();
}
}
FragmentBuildersModule:
@Module
public abstract class FragmentBuildersModule {
@ContributesAndroidInjector(
modules = {ViewModelModule.class, EventsModule.class}
)
abstract EventsFragment contributeEventsFragment();
@ContributesAndroidInjector(
modules = {ViewModelModule.class}
)
abstract ScheduleFragment contributeScheduleFragment();
}
ViewModelFactory:
@Module
public abstract class ViewModelFactoryModule {
@Binds
public abstract ViewModelProvider.Factory bindViewModelFactory(ViewModelProviderFactory modelProviderFactory);
}
ViewModelKey:
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@MapKey
public @interface ViewModelKey {
Class<? extends ViewModel> value();
}
ViewModelModule:
@Module
открытый абстрактный класс ViewModelModule {
@Binds
@IntoMap
@ViewModelKey(EventsViewModel.class)
public abstract ViewModel bindEventsViewModel(EventsViewModel eventsViewModel);
@Binds
@IntoMap
@ViewModelKey(ScheduleViewModel.class)
public abstract ViewModel bindScheduleViewmodel(ScheduleViewModel scheduleViewModel);
BaseApplication:
public class BaseApplication extends DaggerApplication {
@Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
return DaggerAppComponent.builder().application(this).build();
}