简体   繁体   English

Hilt - Java 如何运行时将字符串从 Fragment 注入到 ViewModel 构造函数?

[英]Hilt - Java How to runtime inject String from Fragment to ViewModel constructor?

I have a String inside my Fragment that I'm trying to inject into the Fragment's ViewModel.我的片段中有一个字符串,我试图将其注入片段的 ViewModel。

I've been following this tutorial https://github.com/google/dagger/issues/2287我一直在关注本教程https://github.com/google/dagger/issues/2287

but I can't get the correct syntax from kotlin to java to work.但我无法从 kotlin 到 java 获得正确的语法来工作。

@AssistedFactory
public interface MainViewModelFactory {
    MainViewModel create(String s);
}
@HiltViewModel
public class MainViewModel extends ViewModel {
    private static final String TAG = "MainViewModel";

    @Inject
    public MainViewModel(@Assisted String testString) {
        Log.d(TAG, "MainViewModel: Success injecting: " + testString);
    }

    @SuppressWarnings("unchecked")
    public static ViewModelProvider.Factory provideFactory(
            MainViewModelFactory assistedFactory,
            String s
    ){
        return new ViewModelProvider.Factory() {
            @NonNull
            @Override
            public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
                return (T) assistedFactory.create(s);
            }
        };
    }
}
    @Inject
    MainViewModelFactory viewModelFactory;

    private MainViewModel mainViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        mainViewModel = new ViewModelProvider(this).get(MainViewModel.provideFactory(viewModelFactory, "Test string"));

        //This line fails to even compile because I can't figure out how to fix my syntax from the kotlin to java conversion.
        
    }

在此处输入图像描述

How can I correctly provide the ViewModel from my factory method?如何从我的工厂方法中正确提供ViewModel

When I try to compile it I get当我尝试编译它时,我得到

An assisted factory's abstract method must return a type with an @AssistedInject-annotated constructor. on my factory class's method create .在我的工厂类的方法create

Edit:编辑:

I know you can use a module to provide the string, but I'm using it as a simple example before I try to get it working with injecting an object.我知道您可以使用模块来提供字符串,但在尝试让它与注入 object 一起工作之前,我将它用作一个简单的示例。

Using Hilt 2.37:使用刀柄 2.37:

implementation 'com.google.dagger:hilt-android:2.37'
annotationProcessor 'com.google.dagger:hilt-compiler:2.37'

First, You must add @Inject Annotation On Constructor Of Your Class首先,您必须在 Class 的构造函数上添加 @Inject 注释
Second, if your Constructor of your class has an argument or Object that is hard to Instantiate for dagger, You have to provide it from Module Class.其次,如果你的 class 的构造函数有一个参数或 Object 很难为匕首实例化,你必须从模块 Class 提供它。 for Example if your class use String Class or use an interface, abstract class that cannot be instantiate, you must provide an instance of that class in your Module Class. for Example if your class use String Class or use an interface, abstract class that cannot be instantiate, you must provide an instance of that class in your Module Class.
In your ViewModel Class you can get it like repository class, because repository class is a simple class, dagger knows how to instantiate it, so there is no problem.在您的 ViewModel Class 中,您可以像存储库 class 一样获取它,因为存储库 class 是一个简单的 ZA2F2ED4F8EBC2CBB4C21A29DC40AB6

public class FragmentViewModel extends ViewModel {

    private final RemoteRepository remoteRepository;
    private final TestClass testClass;

    @Inject
    public CardInfoViewModel(RemoteRepository remoteRepository, TestClass testClass) { //How to inject object from Fragment into constructor?
        this.remoteRepository = remoteRepository;
        this.testClass = testClass;
    }
}

module class模块 class

@InstallIn(Singletone.class)
@Module
public class ModuleClass {

    @Singletone
    @Provide
    public TestClass provideTestClass() {
        return new TestClass("Some Text");
    }
}

Took two days to figure it out...but here's how to runtime inject (assisted injection) with hilt using Java.花了两天时间才弄明白...但这里是如何使用 Java 使用刀柄运行时注入(辅助注入)。

Requirements: Dagger 2.31+要求: Dagger 2.31+

Important notes:重要笔记:

DO NOT annotate your ViewModel with @HiltViewModel or it will throw a compile time exception which did not help me identify the issue at all.不要使用@HiltViewModel注释您的 ViewModel,否则它会引发编译时异常,这根本无法帮助我识别问题。

 ViewModel constructor should be annotated with @Inject instead of @AssistedInject.
  [Hilt] Processing did not complete. See error above for details.

Full code with String example:String示例的完整代码:

@AssistedFactory
public interface MainViewModelFactory {
    MainViewModel create(String s);
}
public class MainViewModel extends ViewModel {
    private static final String TAG = "MainViewModel";

    @AssistedInject
    public MainViewModel(@Assisted String testString) {
        Log.d(TAG, "MainViewModel: Success injecting: " + testString);
    }

    @SuppressWarnings("unchecked")
    public static ViewModelProvider.Factory provideFactory(
            MainViewModelFactory assistedFactory,
            String s
    ){
        return new ViewModelProvider.Factory() {
            @NonNull
            @Override
            public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
                return (T) assistedFactory.create(s);
            }
        };
    }
}
@AndroidEntryPoint
public class MainActivity extends AppCompatActivity {

    @Inject
    MainViewModelFactory viewModelFactory;

    private MainViewModel mainViewModel;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        mainViewModel = new ViewModelProvider(
                this, 
                MainViewModel.provideFactory(viewModelFactory, "Test string") 
        ).get(MainViewModel.class);

}

Took me a while to figure out there was a second param for ViewModelProvider which needed the injected ViewModelFactory to create the ViewModelProvider我花了一段时间才发现ViewModelProvider的第二个参数需要注入的ViewModelFactory来创建ViewModelProvider

Hopefully this answer helps people in the future.希望这个答案对未来的人们有所帮助。 I couldn't find any examples of how to do it.我找不到任何如何做到这一点的例子。

Helpful answers:有用的答案:

https://github.com/google/dagger/issues/2287#issuecomment-761811164 https://github.com/google/dagger/issues/2287#issuecomment-761811164

Converting the kotlin way of creating the Java equivalent of ViewModelProviders was quite confusing...转换 kotlin 方法来创建等同于ViewModelProviders的 Java 非常令人困惑......

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

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