【问题标题】:How to make this ViewModelFactory more flexible and accept different kinds of ViewModel classes?如何让这个 ViewModelFactory 更灵活并接受不同种类的 ViewModel 类?
【发布时间】:2018-08-27 06:07:29
【问题描述】:

我复制了一个带有 Android 架构组件、Retrofit、Dagger 和数据绑定的 MVVM 示例。我使用此代码作为我的应用程序的起点,以便开始在 Android 应用程序开发中使用更好的架构。但是,请使用以下代码:

interface ViewModelInjector {
    /**
     * Injects required dependencies into the specified PostListViewModel.
     * @param postListViewModel PostListViewModel in which to inject the dependencies
     */
    fun inject(postListViewModel: PostListViewModel)

    @Component.Builder
    interface Builder {
        fun build(): ViewModelInjector
        fun networkModule(networkModule: NetworkModule): Builder
    }
}

class ViewModelFactory(private val activity: AppCompatActivity) : ViewModelProvider.Factory {
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(PostListViewModel::class.java)) {
            val db = Room.databaseBuilder(
                activity.applicationContext,
                AppDatabase::class.java,
                "posts"
            ).build()

            @Suppress("UNCHECKED_CAST")
            return PostListViewModel(db.postDao()) as T
        }

        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

abstract class BaseViewModel : ViewModel() {
    private val injector: ViewModelInjector = DaggerViewModelInjector
        .builder()
        .networkModule(NetworkModule)
        .build()

    init {
        inject()
    }

    private fun inject() {
        when (this) {
            is PostListViewModel -> injector.inject(this)
        }
    }
}

主要问题是它被PostListViewModel 卡住了。我想以一种动态的方式制作它,接受任何类型的[Name]ViewModel 类。我确实尝试了一些使用Class&lt;T&gt; 的方法,但我不再拥有代码。我也尝试过搜索,但没有得到好的结果。也许我没有搜索合适的术语。我感谢任何指导。

【问题讨论】:

    标签: android android-viewmodel android-mvvm


    【解决方案1】:

    最近我遇到了同样的问题,我发现了一个generic ViewModelFactory,它是 java 但是..

    @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
    @SuppressWarnings("unchecked")
    @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("unknown model class " + modelClass);
        }
        try {
            return (T) creator.get();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    }
    

    我会放参考链接,但我还找不到它..

    编辑:

    @Singleton
    @Component(modules={ActivityModule.class, FragmentModule.class, AppModule.class})
    public interface AppComponents {
    
    @Component.Builder
    interface Builder {
        @BindsInstance
        Builder application(Application application);
        AppComponents build();
    }
    
    void inject(Weather weatherApp);
    }
    

    现在,您对以上课程感兴趣的应该是AppModule.class

    @Module(includes = {UserModelModule.class /* other model modules */})
    public class AppModule {
    
    // --- DATABASE INJECTION ---
    
    @Provides
    @Singleton
    YourDatabase provideDatabase(Application application) {
        return Room.databaseBuilder(application,
                YourDatabase.class, "YourDatabase.db")
                //.allowMainThreadQueries() // do NOT DO THIS IN REAL APPLICATIONs
                .fallbackToDestructiveMigration()
                .build();
    }
    
    @Provides
    @Singleton
    UserDao provideUserDao(YourDatabase database) { return database.userDao(); }
    .
    .
    // other Daos that you will have (the above is an example from [https://developer.android.com/jetpack/docs/guide]
    

    最后,我想你会想看看 ModelModule 类的样子

    @Module
    public abstract class UserModelModule {
    
    @Binds
    @IntoMap
    @ViewModelKey(UserViewModel.class)
    abstract ViewModel bindUserProfileViewModel(UserViewModel repoViewModel);
    
    @Binds
    abstract ViewModelProvider.Factory bindViewModelFactory(ViewModelFactory factory);
    }
    

    【讨论】:

    • 有趣。 databaseBuilder 呢,我应该把它留在那里吗?
    • 请帮帮我,我是新手,对我来说很困惑,太多的代码对我来说没有意义。我应该把Room 数据库实例放在哪里?
    • 嗯,好吧..在这种情况下,您应该放轻松。看看this并完整阅读
    • 好文章。太糟糕了,它没有显示任何关于 Room.databaseBuilder
    • 不过,一开始还是很困难的。我的意思是,我掌握了这个想法,但是很难找到解释更完整但更简单的构建应用程序方法的好文章。我找到的例子总是不完整的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-25
    • 1970-01-01
    相关资源
    最近更新 更多