gpt4 book ai didi

android - 如何创建 ViewModel 并使用 dagger 2 向其注入(inject)存储库?

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:22:25 26 4
gpt4 key购买 nike

我尝试理解 ViewModel。我创建 ViewModel:

public class UsersViewModel extends ViewModel {

private final UsersRepository usersRepository;

public UsersViewModel(UsersRepository usersRepository) {
this.usersRepository = usersRepository;
}

public LiveData<List<User>> loadAll() {
return usersRepository.getAll();
}

}

但我不明白两件事:

  1. 如何将 UsersRepository 注入(inject)此 VievModel?当我使用 Presenter 时,我可以像这样用 Dagger 2 创建它:
@Module
public class PresentersModule {

@Singleton
@Provides
UsersPresenter provideUsersPresenter(UsersRepository usersRepository) {
return new UsersPresenter(usersRepository);
}
}

但是我如何使用 ViewModel 来做到这一点?像这样?

@Module
public class ViewModelsModule {

@Singleton
@Provides
UsersViewModel provideUsersViewModel(UsersRepository usersRepository) {
return new UsersViewModel(usersRepository);
}
}
  1. 如何在 fragment 中获取此 ViewModel?有了 Presenter,我可以做到这一点:

    presenter = MyApplication.get().getAppComponent().getUsersPresenter();

最佳答案

ViewModel 是通过 ViewModelProvider 创建的,它使用 ViewModelFactory 来创建实例。您不能直接注入(inject) ViewModel,而应该使用如下所示的自定义工厂

@Singleton
public class DaggerViewModelFactory implements ViewModelProvider.Factory {
private final Map<Class<? extends ViewModel>, Provider<ViewModel>> creators;

@Inject
public DaggerViewModelFactory(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);
}
}
}

然后您需要一个用于创建 View 模型工厂和 View 模型本身的 Dagger 模块。

@Module
abstract class ViewModelModule {
@Binds
abstract ViewModelProvider.Factory bindViewModelFactory(DaggerViewModelFactory factory);

@Binds
@IntoMap
@ViewModelKey(VideoListViewModel.class)
abstract ViewModel provideVideoListViewModel(VideoListViewModel videoListViewModel);

@Binds
@IntoMap
@ViewModelKey(PlayerViewModel.class)
abstract ViewModel providePlayerViewModel(PlayerViewModel playerViewModel);

@Binds
@IntoMap
@ViewModelKey(PlaylistViewModel.class)
abstract ViewModel providePlaylistViewModel(PlaylistViewModel playlistViewModel);

@Binds
@IntoMap
@ViewModelKey(PlaylistDetailViewModel.class)
abstract ViewModel providePlaylistDetailViewModel(PlaylistDetailViewModel playlistDetailViewModel);
}

ViewModelKey文件是这样的

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@MapKey
@interface ViewModelKey {
Class<? extends ViewModel> value();
}

现在要在 Activity 或 fragment 中获取 View 模型,只需注入(inject) View 模型工厂,然后使用该工厂创建 View 模型实例

public class PlayerActivity extends BaseActivity {
@Inject DaggerViewModelFactory viewModelFactory;
PlayerViewModel viewModel;

@Override
protected void onCreate(Bundle savedInstanceState) {
AndroidInjection.inject(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_player);
viewModel = ViewModelProviders.of(this,viewModelFactory).get(PlayerViewModel.class);

}

要向您的 ViewModel 注入(inject)任何东西,例如存储库,只需使用构造函数注入(inject)。

public class PlayerViewModel extends ViewModel {
private VideoRepository videoRepository;
private AudioManager audioManager;


@Inject
public PlayerViewModel(VideoRepository videoRepository, AudioManager audioManager) {
this.videoRepository = videoRepository;
this.audioManager = audioManager;

}
}

从这里查看完整的工作示例 https://github.com/alzahm/VideoPlayer ,我还从谷歌样本中学到了很多 Dagger 的东西,你也可以检查一下。

关于android - 如何创建 ViewModel 并使用 dagger 2 向其注入(inject)存储库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51232149/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com