ViewModelFactory 和 AndroidInjection 的 Dagger 循环依赖问题

问题描述 投票:0回答:1

我想了解为什么我在这里有匕首循环依赖:

class MachineFragment : Fragment() {

    @Inject
    lateinit var viewModelFactory: ViewModelFactory

    private lateinit var viewModel: MachinesViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        AndroidSupportInjection.inject(this)
        super.onCreate(savedInstanceState)
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        super.onCreateView(inflater, container, savedInstanceState)
        viewModel = ViewModelProvider(this, viewModelFactory).get(MachinesViewModel::class.java)
        return inflater.inflate(R.layout.fragment_machines, container, false)
    }
@Singleton
@Component(
    dependencies = [],
    modules = [
        AppModule::class,
        TestViewModelModule::class,
        InjectorModule::class
    ]
)
interface AppComponent {

    fun inject(subject: AppApplication)

public abstract class TestViewModelModule {

    @Binds
    public abstract ViewModelFactory bindViewModelFactory(ViewModelFactory viewModelFactory);

    /*
        you have to explicitly define ViewModel instead of concrete
        implementation to avoid cycle dependency error
    */
    @Binds
    @IntoMap
    @ViewModelKey(MachinesViewModel.class)
    abstract ViewModel bindMachinesViewModel(MachinesViewModel vm);
}
public class ViewModelFactory implements ViewModelProvider.Factory {

    private final Map<Class<? extends ViewModel>, Provider<ViewModel>> viewModels;

    @Inject
    public ViewModelFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> viewModels) {
        this.viewModels = viewModels;
    }

    @Override
    public <T extends ViewModel> T create(Class<T> modelClass) {
        Provider<ViewModel> viewModelProvider = viewModels.get(modelClass);

        if (viewModelProvider == null) {
            throw new IllegalArgumentException("model class " + modelClass + " not found");
        }

        return (T) viewModelProvider.get();
    }

}

但是,当我在

MainActivity
中定义相同的注入字段时,循环依赖性消失了:

class MainActivity : AppCompatActivity() {

    @Inject
    lateinit var viewModelFactory: ViewModelFactory

    private lateinit var viewModel: MachinesViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        AndroidInjection.inject(this)
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        /* start destination in navigation.xml defines entry point */

        viewModel = ViewModelProvider(this, viewModelFactory).get(MachinesViewModel::class.java)
    }

我已经通过添加

@Named("machine-vm-factory")
注释解决了这个问题,但我不清楚根本原因。我会感谢您对此的想法。谢谢!

android android-viewmodel dagger
1个回答
0
投票

我认为问题在于

TestViewModelModule
中的这一行:

@Binds
public abstract ViewModelFactory bindViewModelFactory(ViewModelFactory viewModelFactory);

在这里,当有人请求

ViewModelFactory
时,你要求 Dagger 给你一个
ViewModelFactory
,并且由于
@Binds
的优先级高于
@Inject
,Dagger 并不真正知道如何构造
ViewModelFactory
,因此循环。

添加限定符会改变关键:

@Binds
@Named("machine-vm-factory")
public abstract ViewModelFactory bindViewModelFactory(ViewModelFactory viewModelFactory);

这意味着当有人请求

@Named("machine-vm-factory") ViewModelFactory
时,Dagger 会使用
ViewModelFactory
带注释的构造函数给我们一个
@Inject
,这样循环就消失了。

参见 https://dagger.dev/semantics/#keys

© www.soinside.com 2019 - 2024. All rights reserved.