使用dagger 2的Android生命周期库ViewModel

The*_*mer 48 android android-lifecycle dagger-2

我有一个ViewModel类,就像在Architecture指南Connecting ViewModel和repository部分中定义的那样.当我运行我的应用程序时,我得到运行时异常.有谁知道怎么解决这个问题?我应该不注入ViewModel吗?有没有办法告诉使用Dagger创建模型?ViewModelProvider

public class DispatchActivityModel extends ViewModel {

    private final API api;

    @Inject
    public DispatchActivityModel(API api) {
        this.api = api;
    }
}
Run Code Online (Sandbox Code Playgroud)

引起:java.lang.InstantiationException:java.lang.Class在java.lang.Class.newInstance(Native Method)的android.arch.lifeModelProvider $ NewInstanceFactory.create(ViewModelProvider.java:143)中没有零参数构造函数在Android.arch.lifecycle.ViewModelProvider.get上的android.arch.lifecycle.ViewModelProviders $ DefaultFactory.create(ViewModelProviders.java:143)android.arch.lifecycle.ViewModelProvider.get(ViewModelProvider.java:128)(ViewModelProvider.java) :96)com.example.base.BaseActivity.onCreate(BaseActivity.java:65)at com.example.dispatch.DispatchActivity.onCreate(DispatchActivity.java:53)at android.app.Activity.performCreate(Activity.java: 6682)在android.app.Anstrumentation.callActivityOnCreate(Instrumentation.java:1118)的android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2619)android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2727). android.app.ActivityT上的app.ActivityThread.-wrap12(ActivityThread.java)在android.app.ActivityThread.main上的android.os.Handler.dispatchMessage(Handler.java:102)上的android.os.Looper.loop(Looper.java:154)处获取$ H.handleMessage(ActivityThread.java:1478) (ActivityThread.java:6121)

小智 85

你需要实现自己的ViewModelProvider.Factory.Google创建了一个示例应用,演示如何将Dagger 2与ViewModels连接.链接.你需要这5件事:

在ViewModel中:

@Inject
public UserViewModel(UserRepository userRepository, RepoRepository repoRepository) {
Run Code Online (Sandbox Code Playgroud)

定义注释:

@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@MapKey
@interface ViewModelKey {
    Class<? extends ViewModel> value();
}
Run Code Online (Sandbox Code Playgroud)

在ViewModelModule中:

@Module
abstract class ViewModelModule {
    @Binds
    @IntoMap
    @ViewModelKey(UserViewModel.class)
    abstract ViewModel bindUserViewModel(UserViewModel userViewModel);
Run Code Online (Sandbox Code Playgroud)

在片段中:

@Inject
ViewModelProvider.Factory viewModelFactory;

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
            userViewModel = ViewModelProviders.of(this, viewModelFactory).get(UserViewModel.class);
Run Code Online (Sandbox Code Playgroud)

厂:

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

    @Inject
    public GithubViewModelFactory(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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 您还必须声明:`@Binds abstract ViewModelProvider.Factory bindViewModelFactory(GithubViewModelFactory factory);`在您的ViewModelModule中 (9认同)
  • 您还需要定义@ViewModelKey https://github.com/googlesamples/android-architecture-components/blob/388a10dd5a814ba6aaa9bf8dee8e7c1c5840b3a5/GithubBrowserSample/app/src/main/java/com/android/example/github/di/ViewModelKey.java (5认同)
  • 欢迎来到Stack Overflow.我们总是欢迎指向潜在解决方案的链接,但请在链接周围添加上下文,以便您的其他用户能够了解它是什么以及它为什么存在.如果目标站点无法访问或永久脱机,请始终引用重要链接的最相关部分.看看[为什么以及如何删除某些答案?](https://stackoverflow.com/help/deleted-answers)和[我如何写出一个好的答案?](https://stackoverflow.com/help /如何到结果) (4认同)
  • 我相信此答案中缺少一些内容。我仍然让我的工厂为null,Android退回到默认工厂,并产生“没有零参数构造函数”异常。 (2认同)

arg*_*iwi 25

今天我学会了一种避免为我的ViewModel课程编写工厂的方法:

class ViewModelFactory<T : ViewModel> @Inject constructor(
    private val viewModel: Lazy<T>
) : ViewModelProvider.Factory {
    @Suppress("UNCHECKED_CAST")
    override fun <T : ViewModel?> create(modelClass: Class<T>): T = viewModel.get() as T
}
Run Code Online (Sandbox Code Playgroud)

编辑:正如@Calin在评论中指出的那样,我们Lazy在上面的代码片段中使用Dagger ,而不是Kotlin的.

ViewModel您可以将一个泛型ViewModelFactory注入到您的活动和片段中,而不是注入它,并获取任何实例ViewModel:

class MyActivity : Activity() {

    @Inject
    internal lateinit var viewModelFactory: ViewModelFactory<MyViewModel>
    private lateinit var viewModel: MyViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
        this.viewModel = ViewModelProviders.of(this, viewModelFactory)
            .get(MyViewModel::class.java)
        ...
    }

    ...
}
Run Code Online (Sandbox Code Playgroud)

AndroidInjection.inject(this)dagger-android库一样使用,但您可以按照自己喜欢的方式注入活动或片段.剩下的就是确保您ViewModel从模块中提供:

@Module
object MyModule {
    @JvmStatic
    @Provides
    fun myViewModel(someDependency: SomeDependency) = MyViewModel(someDependency)
} 
Run Code Online (Sandbox Code Playgroud)

或者将@Inject注释应用于其构造函数:

class MyViewModel @Inject constructor(
    someDependency: SomeDependency
) : ViewModel() {
    ...
}
Run Code Online (Sandbox Code Playgroud)

  • 啊得到它,是匕首懒惰,而不是从kotlin懒惰:( (3认同)
  • 内联乐趣 &lt;reified T : ViewModel&gt; ViewModelFactory&lt;T&gt;.get(activity:FragmentActivity): T = ViewModelProviders.of(activity, this).get(T::class.java) (2认同)