簡體   English   中英

Hilt - Java 如何運行時將字符串從 Fragment 注入到 ViewModel 構造函數?

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

我的片段中有一個字符串,我試圖將其注入片段的 ViewModel。

我一直在關注本教程https://github.com/google/dagger/issues/2287

但我無法從 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.
        
    }

在此處輸入圖像描述

如何從我的工廠方法中正確提供ViewModel

當我嘗試編譯它時,我得到

An assisted factory's abstract method must return a type with an @AssistedInject-annotated constructor. 在我的工廠類的方法create

編輯:

我知道您可以使用模塊來提供字符串,但在嘗試讓它與注入 object 一起工作之前,我將它用作一個簡單的示例。

使用刀柄 2.37:

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

首先,您必須在 Class 的構造函數上添加 @Inject 注釋
其次,如果你的 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.
在您的 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;
    }
}

模塊 class

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

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

花了兩天時間才弄明白...但這里是如何使用 Java 使用刀柄運行時注入(輔助注入)。

要求: Dagger 2.31+

重要筆記:

不要使用@HiltViewModel注釋您的 ViewModel,否則它會引發編譯時異常,這根本無法幫助我識別問題。

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

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

}

我花了一段時間才發現ViewModelProvider的第二個參數需要注入的ViewModelFactory來創建ViewModelProvider

希望這個答案對未來的人們有所幫助。 我找不到任何如何做到這一點的例子。

有用的答案:

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

轉換 kotlin 方法來創建等同於ViewModelProviders的 Java 非常令人困惑......

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM