无法获得匕首注入Viewmodel

我一直在遵循在Android应用程序中设置DI的指南,据我所知,我已经正确设置了所有设置。但是,出现以下错误:

java.lang.RuntimeException: Cannot create an instance of class com.topper.topper.ui.viewmodel.ProfileViewModel

以下是我的课程的简化版本(为简洁起见):

activityModule

@Module
public abstract class activityModule {
    @ContributesAndroidInjector(modules = FragmentModule.class)
    abstract Mainactivity contributeMainactivity();
}

FragmentModule

@Module
public abstract class FragmentModule {
    @ContributesAndroidInjector
    abstract ProfileFragment contributeProfileFragment();
}

ViewModelModule

@Module
public abstract class ViewModelModule {
    @Binds
    @IntoMap
    @ViewModelKey(ProfileViewModel.class)
    abstract ViewModel bindProfileViewModel(ProfileViewModel profileViewModel);

    @Binds
    abstract ViewModelProvider.Factory bindViewModelFactory(ViewModelFactory factory);
}

AppModule

@Module(includes = ViewModelModule.class)
public class AppModule {

    @Provides
    @Singleton
    TopperDB provideDatabase(Application application) {
        return Room.databaseBuilder(application,TopperDB.class,"TopperDB.db")
                .build();
    }

    @Provides
    @Singleton
    CachedImageDao provideCachedImageDao(TopperDB database) {
        return database.cachedImageDao();
    }

    @Provides
    @Singleton
    Executor provideExecutor() {
        return Executors.newSingleThreadExecutor();
    }

    @Provides
    @Singleton
    CachedImageRepository provideCachedImageRepository(CachedImageDao cachedImageDao,Executor executor) {
        return new CachedImageRepository(cachedImageDao,executor);
    }
}

AppComponent

@Singleton
@Component(modules = {AndroidSupportInjectionmodule.class,AndroidInjectionmodule.class,activityModule.class,FragmentModule.class,AppModule.class})
public interface AppComponent {

    void inject(TopperApp app);

    @Component.Builder
    interface Builder {
        @BindsInstance
        Builder application(Application application);

        AppComponent build();
    }
}

ViewModelKey

@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@MapKey
public @interface ViewModelKey {
    Class<? extends ViewModel> value();
}

ViewModelFactory

@Singleton
public class ViewModelFactory implements ViewModelProvider.Factory {

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

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

    @NotNull
    @SuppressWarnings("unchecked")
    @Override
    public <T extends ViewModel> T create(@NotNull Class<T> modelClass) {
        Provider<? extends ViewModel> creator = creators.get(modelClass);
        if (creator == null) {
            for (Map.Entry<Class<? extends ViewModel>,Provider<ViewModel>> entry : creators.entryset()) {
                if (modelClass.isAssignableFrom(entry.getKey())) {
                    creator = entry.getvalue();
                    break;
                }
            }
        }
        if (creator == null) {
            throw new IllegalArgumentException("unknown model class " + modelClass);
        }
        try {
            return (T) creator.get();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

CachedImageRepository

@Singleton
public class CachedImageRepository extends BaseRepository {

    private final CachedImageDao cachedImageDao;
    private final Executor executor;

    @Inject
    public CachedImageRepository(CachedImageDao cachedImageDao,Executor executor) {
        this.cachedImageDao = cachedImageDao;
        this.executor = executor;
    }
}

ProfileViewModel

public class ProfileViewModel extends ViewModel {

    private CachedImageRepository cachedImageRepo;

    @Inject
    public ProfileViewModel(CachedImageRepository cachedImageRepo) {
        this.cachedImageRepo = cachedImageRepo;
    }
}

ProfileFragment

public class ProfileFragment extends BaseFragment {

    @Inject
    ViewModelProvider.Factory viewModelFactory;

    private ProfileViewModel mViewModel;

    @Override
    public void onactivityCreated(@Nullable Bundle savedInstanceState) {
        super.onactivityCreated(savedInstanceState);
        configureDagger();
    }

    public View onCreateView(@NonNull LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {

        FragmentProfileBinding binding = DataBindingUtil.inflate(inflater,R.layout.fragment_profile,container,false);

        mViewModel = ViewModelProviders.of(this.requireactivity(),viewModelFactory).get(ProfileViewModel.class);
        mViewModel.init();
        binding.setProfileViewModel(mViewModel);

        return binding.getRoot();
    }

    private void configureDagger() {
        AndroidSupportInjection.inject(this);
    }

}

Mainactivity

public class Mainactivity extends AppCompatactivity implements ProgressDisplay,HasSupportFragmentInjector {

    @Inject
    DispatchingAndroidInjector<Fragment> dispatchingAndroidInjector;

    @Inject
    ViewModelProvider.Factory viewModelFactory;

    private AppBarLayout appBarLayout;

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

        this.configureDagger();
    }

    private void configureDagger() {
        AndroidInjection.inject(this);
    }

}

TopperApp

public class TopperApp extends Application implements HasactivityInjector {

    public Context ctx;
    @Inject
    DispatchingAndroidInjector<activity> dispatchingAndroidInjector;

    @Override
    public void onCreate() {
        super.onCreate();
        this.initDagger();
        ctx = getapplicationContext();
    }

    public Context getappContext() {
        return ctx;
    }

    @Override
    public DispatchingAndroidInjector<activity> activityInjector() {
        return dispatchingAndroidInjector;
    }

我想我已经包括了以上所有相关细节,但是如果我错过了任何事情,请告诉我。

任何帮助将不胜感激,我已经将头撞在墙上几天了。

谢谢。

编辑:如果有帮助,我尝试向 ProfileViewModel 中添加一个空构造函数,这将导致以下错误:

java.lang.NullPointerException: Attempt to invoke virtual method 'void com.topper.topper.data.repo.CachedImageRepository.cacheImage(android.content.Context,java.lang.String,int)' on a null object reference

因此,匕首似乎没有注入到ProfileViewModel的构造函数中。

huazi1234567890123 回答:无法获得匕首注入Viewmodel

发现问题出在我的Fragment类中。

更改自;

public class ProfileFragment extends BaseFragment {

    @Inject
    ViewModelProvider.Factory viewModelFactory;

    private ProfileViewModel mViewModel;

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        configureDagger();
    }

    public View onCreateView(@NonNull LayoutInflater inflater,ViewGroup container,Bundle savedInstanceState) {

        FragmentProfileBinding binding = DataBindingUtil.inflate(inflater,R.layout.fragment_profile,container,false);

        mViewModel = ViewModelProviders.of(this.requireActivity(),viewModelFactory).get(ProfileViewModel.class);
        mViewModel.init();
        binding.setProfileViewModel(mViewModel);

        return binding.getRoot();
    }

    private void configureDagger() {
        AndroidSupportInjection.inject(this);
    }

}

public class ProfileFragment extends BaseFragment {

    @Inject
    ViewModelProvider.Factory viewModelFactory;

    private ProfileViewModel mViewModel;

    public View onCreateView(@NonNull LayoutInflater inflater,Bundle savedInstanceState) {

        configureDagger();

        FragmentProfileBinding binding = DataBindingUtil.inflate(inflater,viewModelFactory).get(ProfileViewModel.class);
        mViewModel.init();
        binding.setProfileViewModel(mViewModel);

        return binding.getRoot();
    }

    private void configureDagger() {
        AndroidSupportInjection.inject(this);
    }

}
,

Dagger无法独自创建ViewModel。 ViewModel实例化是通过ViewModelProvider.Factory的一个实例完成的。 您需要告诉匕首它如何创建ProfileViewModel.

的实例

因此,@Binds在这种情况下对您不起作用。您需要定义一个方法,该方法返回一个ProfileViewModel的实例,并用 @Provides 对其进行注释。

例如-

@Module
public class ViewModelModule {

@Provides
@IntoMap
@ViewModelKey(ProfileViewModel.class)
public ProfileViewModel bindProfileViewModel(ViewModelFactory factory) {
    return factory.create();
}

@Provides
public ViewModelProvider.Factory bindViewModelFactory(){
    return new ViewModelFactory();
}

有关更多详细信息,请参考-

Why a viewmodel factory is needed in Android?

本文链接:https://www.f2er.com/3167425.html

大家都在问