Dagger 2 ViewModelProvider.Factory被多次绑定

5

我正在尝试使用片段创建一个应用程序。我创建了一个测试片段(HomeFragment),其中只包含一个简单的TextView。我创建了所有必要的类(模块、模型和提供者)。但是我遇到了一种奇怪的复杂错误。

Error:(25, 10) error: [dagger.android.AndroidInjector.inject(T)] android.arch.lifecycle.ViewModelProvider.Factory is bound multiple times:
@Provides android.arch.lifecycle.ViewModelProvider.Factory app.series.com.series3go.ui.main.MainActivityModule.mainViewModelProvider(app.series.com.series3go.ui.main.MainViewModel)
@Provides android.arch.lifecycle.ViewModelProvider.Factory app.series.com.series3go.ui.home.HomeFragmentModule.provideHomeFragmentViewModel(app.series.com.series3go.ui.home.HomeFragmentViewModel)

HomeFragment

public class HomeFragment extends BaseFragment<HomeFragmentBinding, HomeFragmentViewModel> {

public static final String TAG = HomeFragment.class.getSimpleName();
@Inject
ViewModelProvider.Factory mViewModelFactory;


HomeFragmentBinding mHomeFragmentBinding;
private HomeFragmentViewModel mHomeFragmentViewModel;

public static HomeFragment newInstance() {
    Bundle args = new Bundle();
    HomeFragment fragment = new HomeFragment();
    fragment.setArguments(args);
    return fragment;
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    mHomeFragmentBinding = getViewDataBinding();
    setUp();
    subscribeToLiveData();
}

@Override
public HomeFragmentViewModel getViewModel() {
    mHomeFragmentViewModel = ViewModelProviders.of(this, mViewModelFactory).get(HomeFragmentViewModel.class);
    return mHomeFragmentViewModel;
}

@Override
public int getBindingVariable() {
    return BR.viewModel;
}

@Override
public int getLayoutId() {
    return R.layout.home_fragment;
}

private void setUp() {

}

private void subscribeToLiveData() {

}
@Override
public void onDestroyView() {
    super.onDestroyView();
}


}

HomeFragmentModule

@Module
public class HomeFragmentModule
{

    @Provides
    HomeFragmentViewModel homeFragmentViewModel()
    {
        return new HomeFragmentViewModel();
    }

    @Provides
    ViewModelProvider.Factory provideHomeFragmentViewModel(HomeFragmentViewModel homeFragmentViewModel)
    {
        return new ViewModelProviderFactory<>(homeFragmentViewModel);
    }

}

HomeFragmentProvider

@Module
public abstract class HomeFragmentProvider {

    @ContributesAndroidInjector(modules = HomeFragmentModule.class)
    abstract HomeFragment provideHomeFragmentFactory();

} 

HomeFragmentViewModel

公共类 HomeFragmentViewModel 继承自 BaseViewModel {

private final ObservableField<String> appVersion = new ObservableField<>();

public HomeFragmentViewModel() {
    super();
    appVersion.set("123");
}

public ObservableField<String> getAppVersion() {
    return appVersion;
}

}

home_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="app.series.com.series3go.ui.main.MainActivity">

    <data>

        <import type="android.view.View" />

        <variable
            name="viewModel"
            type="app.series.com.series3go.ui.home.HomeFragmentViewModel" />

    </data>


    <TextView
        android:id="@+id/tvAppVersion"
        style="@style/TextStyle.Title.Sub"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:padding="5dp"
        android:text="@{viewModel.appVersion}" />

</layout>

在提供者类(HomeFragmentProvider)中,函数命名是否有约定?我没有看到项目中任何地方使用这些函数。它们在dagger生成的类中使用吗?

谢谢!

更新

AppComponent

@Singleton
@Component(modules = {AndroidSupportInjectionModule.class, AppModule.class, ActivityBuilder.class})
public interface AppComponent {

    @Component.Builder
    interface Builder {

        @BindsInstance
        Builder application(Application application);

        AppComponent build();

    }

    void inject(SeriesApp app);

}

同时分享Dagger组件。 - azizbekian
更新了我的主贴。 - Anton Makov
2个回答

24

看起来你的依赖图中有两个提供 ViewModelProvider.Factory 的方法。

为了解决这个歧义,使用 @Named 注释。

@Module
public class HomeFragmentModule {
    @Provides
    @Named("HomeFragment")
    ViewModelProvider.Factory provideHomeFragmentViewModel(HomeFragmentViewModel homeFragmentViewModel) {
        return new ViewModelProviderFactory<>(homeFragmentViewModel);
    }
    /* Rest of the code */
}

public class HomeFragment {
    @Inject
    @Named("HomeFragment")
    ViewModelProvider.Factory mViewModelFactory;
    /* Rest of the code */
}

你也应该为第二个 ViewModelProvider.Factory 做同样的事情(在 MainActivity 及其模块中)。


我添加了@Named注释,但我不明白应该在哪里使用它,它说当我使用Inject注释时需要使用它,但我没有使用它,我只是使用provides。 - Anton Makov
你的解决方案有效,但现在在ViewModelFactory中出现了活动和片段的ViewModel冲突。对此有什么想法吗? - Shweta Chauhan
1
@ShwetaChauhan 这看起来像是一个在SO上的独立问题。 - dev.bmax

1
我将编辑错误日志以使其更易理解:
错误:ViewModelProvider.Factory被绑定多次: @Provides ViewModelProvider.Factory MainActivityModule.mainViewModelProvider(MainViewModel) @Provides ViewModelProvider.Factory HomeFragmentModule.provideHomeFragmentViewModel(HomeFragmentViewModel)
你在HomeFragment中声明了你想要注入ViewModelProvider.Factory。Dagger试图找到提供程序方法,并找到两个:一个是从MainActivityModule提供的,另一个是从HomeFragmentModule提供的。因此,Dagger感到困惑并停止编译。
我建议您采用类似于Google展示应用程序GithubBrowserSample中的方法。在该应用程序中,使用@IntoMap注释将ViewModels注入到映射(Map<Class, ViewModel>)中。在您的情况下,您将会将ViewModelProvider.Factory注入到映射中。
您可以在GithubViewModelFactory中看到映射的注入。
或者,您可以考虑@dev.bmax提出的方法

说实话,我有点困惑,我从这个例子中看到了ViewModelModule类,但是我在底部看到了bindViewModelFactory函数,我是否也应该使用他们的GithubViewModelFactory,而且我没有看到任何人使用ViewModelModule。 - Anton Makov
我不知道你具体的使用情况,但在我看来,最可能的情况是你不需要注入ViewModelProvider.Factor,而是应该有一个工厂和多个ViewModel - azizbekian
我添加了ViewModelModule并进行了必要的更改,从模块中删除了ViewModelProvider.Factory mainViewModelProvider和ViewModelProvider.Factory provideHomeFragmentViewModel。我没有对我的ViewModelProviderFactory进行任何更改,但是我遇到了错误。 - Anton Makov
你希望我猜测你遇到了哪些错误吗? - azizbekian
请在您的问题中更新您收到的错误信息。 - azizbekian
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接