简体   繁体   English

Dagger 2 ViewModelProvider.Factory绑定多次

[英]Dagger 2 ViewModelProvider.Factory bound multiple times

I'm trying to create an application while using fragments. 我正在尝试使用片段创建一个应用程序。 I created a test fragment (HomeFragment) it has only a simple TextView. 我创建了一个测试片段(HomeFragment),它只有一个简单的TextView。 I created all the necessary classes (module, model and provider). 我创建了所有必需的类(模块,模型和提供程序)。 But I'm getting a strange complication error 但是我收到一个奇怪的并发症错误

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 HomeFragment模块

@Module
public class HomeFragmentModule
{

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

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

}

HomeFragmentProvider HomeFragmentProvider

@Module
public abstract class HomeFragmentProvider {

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

} 

HomeFragmentViewModel HomeFragmentViewModel

public class HomeFragmentViewModel extends BaseViewModel { 公共类HomeFragmentViewModel扩展BaseViewModel {

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

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

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

} }

home_fragment.xml 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>

Is there a naming convention about function names in provider class(HomeFragmentProvider), I didn't see any use of those functions any where in the project. 在提供程序类(HomeFragmentProvider)中是否有关于函数名称的命名约定,我在项目中的任何地方都没有看到对这些函数的任何使用。 Are they used in the generated classes of dagger? 它们用于生成的匕首类中吗?

Thanks 谢谢

UPDATE 更新

AppComponent 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);

}

Looks like you have two methods in your dependency graph that provide ViewModelProvider.Factory . 看起来您的依赖图中有两个提供ViewModelProvider.Factory

To solve this ambiguity, use @Named annotation. 要解决这种歧义,请使用@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 */
}

You should do the same for the second ViewModelProvider.Factory too (in MainActivity and it's module). 您也应该对第二个ViewModelProvider.Factory进行相同的操作(在MainActivity及其模块中)。

I will edit error log in order to make it a bit more understandable: 我将编辑错误日志,以使其更易于理解:

Error: ViewModelProvider.Factory is bound multiple times: 错误:ViewModelProvider.Factory被绑定多次:

@Provides ViewModelProvider.Factory MainActivityModule.mainViewModelProvider(MainViewModel) @提供ViewModelProvider.Factory MainActivityModule.mainViewModelProvider(MainViewModel)

@Provides ViewModelProvider.Factory HomeFragmentModule.provideHomeFragmentViewModel(HomeFragmentViewModel) @提供ViewModelProvider.Factory HomeFragmentModule.provideHomeFragmentViewModel(HomeFragmentViewModel)

You have declared inside HomeFragment , that you are willing to inject ViewModelProvider.Factory . 您已经在HomeFragment声明了您愿意注入ViewModelProvider.Factory Dagger tries to find a provider method and finds two of them: one is being provided from MainActivityModule , the other from HomeFragmentModule . Dagger尝试查找提供程序方法,并找到其中两个:一个是从MainActivityModule提供的,另一个是HomeFragmentModule So, dagger gets confused and aborts compilation. 因此,匕首会造成混乱并中止编译。

I would suggest you to adopt the approach similar to what is present in Google's showcase GithubBrowserSample app. 我建议您采用类似于Google展示柜GithubBrowserSample应用程序中的方法。 In that app ViewModels are being injected into a map ( Map<Class, ViewModel> ) using @IntoMap annotation. 在该应用程序ViewModels 被注入到地图( Map<Class, ViewModel>使用) @IntoMap注释。 In your case you would inject ViewModelProvider.Factory -ies into map. 在您的情况下,您可以将ViewModelProvider.Factory -ies注入到地图中。

You can see the injection of the map inside GithubViewModelFactory . 您可以在GithubViewModelFactory看到地图的注入。

Alternatively, you may consider approach suggested by @dev.bmax. 或者,您可以考虑@ dev.bmax建议的方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM