ViewModel constructor should be annotated with @Inject instead of @AssistedInject
Asked Answered
D

1

11

I want to provide some dependency at run time to ViewModel using Hilt. I have followed the solution that was directed by d.android.com this.

@HiltViewModel    
public class ViewViewModel extends ViewModel {
    ...
    @AssistedFactory
    public interface ViewViewModelFactory {
        ViewViewModel create(@Assisted int version);
    }

    @AssistedInject
    public ViewViewModel(ProfileRepository repository, @Assisted int version) {
        mProfileRepository = repository;
    }
}

@AndroidEntryPoint
public class CarFragment extends Fragment {
    @Inject
    ViewViewModel.ViewViewModelFactory mViewViewModelFactory;

    ...

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        ViewViewModel viewModel = mViewViewModelFactory.create(21);
    }
}

However, still getting the build error ViewModel constructor should be annotated with @Inject instead of @AssistedInject.

I am using hilt version 2.38.1 and AGP version 7.0.0. Also tried with some earlier version (2.35, 2.37).

I have also tried creating my own Factory Provider without any luck:

public class ViewViewModel extends ViewModel {
...
@AssistedFactory
public interface ViewViewModelFactory {
    ViewViewModel create(@Assisted int version);
}

@AssistedInject
public ViewViewModel(ProfileRepository repository, @Assisted int version) {
    mProfileRepository = repository;
}

public static ViewViewModel provideFactory(ViewViewModelFactory assistedFactory,
                             int version){
    return new ViewViewModelFactoryProvider(assistedFactory,version).create(ViewViewModel.class);
}

public static class ViewViewModelFactoryProvider implements ViewModelProvider.Factory {
    ViewViewModelFactory assistedFactory;
    int version;

    public ViewViewModelFactoryProvider(ViewViewModelFactory assistedFactory,
                                           int version) {
        this.assistedFactory = assistedFactory;
        this.version = version;
    }

    @NonNull
    @Override
    public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
        return (T) assistedFactory.create(version);
    }
}

}

@AndroidEntryPoint
public class CarFragment extends Fragment {
    @Inject
    ViewViewModel.ViewViewModelFactory mViewViewModelFactory;

    ...

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        ViewViewModel viewModel = ViewViewModel.provideFactory(mViewViewModelFactory,21);
    }

}

Diverting answered 4/8, 2021 at 10:15 Comment(3)
I have the same issue. When I use @Inject the error is: @Assisted parameters can only be used within an @AssistedInject-annotated constructor.. When I switch Inject to @AssistedInject the error is: ViewModel constructor should be annotated with @Inject instead of @AssistedInjectBennet
there is a solution?Edraedrea
https://mcmap.net/q/332554/-dagger-hilt-39-assisted-39-and-39-viewmodelinject-39-is-deprecated-in-dagger-hilt-view-model-1-0-0-alpha03Rooks
W
8

Remove @HiltViewModel

In the link you mentioned, a comment stated that

In Dagger 2.31, it's possible to achieve the above without using @HiltViewModel and passing everything manually

I see that the rest of the implementation is already done so removing @HiltViewModel should do it.

Withdrawal answered 11/8, 2021 at 15:8 Comment(1)
No. This will create the object with assisted injection but will lose the functionality of the ViewModel e.g. saving state on configuration change. Therefore, if we remove @HiltViewModel it will not be used by dagger as a ViewModel, instead, it will be used as a regular factory.Diverting

© 2022 - 2024 — McMap. All rights reserved.