Dagger MVVM - ViewModel注入为null

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dagger MVVM - ViewModel注入为null相关的知识,希望对你有一定的参考价值。

我试图使用Dagger2在一个片段中注入ViewModel,但我得到了一个NullPointerException。以下是片段和堆栈跟踪。

private CompositeDisposable disposable = new CompositeDisposable();
@Inject
MovieViewModel viewModel;

@BindView(R.id.movies_recycler_view)
RecyclerView recyclerView;

public MoviesFragment() {
    // Required empty public constructor
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}


@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.movies_menu, menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();

    switch (id) {
        case R.id.sort_by:
            topRatedSubscription();
            break;
        case R.id.sort_by_popular:
            moviesSubscription();
            break;
    }

    return super.onOptionsItemSelected(item);
}


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

    View view = inflater.inflate(R.layout.movies_fragment_content, container, false);
    ButterKnife.bind(this, view);
    GridLayoutManager layoutManager = new GridLayoutManager(getContext(), COLUMN_COUNT);

    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setItemAnimator(new DefaultItemAnimator());

    adapter = new MoviesGridAdapter(getContext(), resultItems);
    recyclerView.setAdapter(adapter);

    return view;
}


private void moviesSubscription() {


    disposable.add(viewModel.discoverMovies(Constants.MOVIE_API_KEY)
            .observeOn(androidSchedulers.mainThread()
            ).subscribe(
                    response -> adapter.setMovies(response.getResults())
            ));

}

private void topRatedSubscription() {
}

@Override
public void onResume() {
    super.onResume();
    moviesSubscription();
}


Process: com.example.mchapagai, PID: 5986
                                                                         java.lang.RuntimeException: Unable to resume activity {com.example.mchapagai/com.example.activity.MoviesActivity}: java.lang.NullPointerException: Attempt to invoke interface method 'io.reactivex.Observable com.example.viewmodel.MovieViewModel.discoverMovies(java.lang.String)' on a null object reference
                                                                             at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3581)
                                                                             at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3621)
                                                                             at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2862)
                                                                             at android.app.ActivityThread.-wrap11(Unknown Source:0)
                                                                             at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
                                                                             at android.os.Handler.dispatchMessage(Handler.java:106)
                                                                             at android.os.Looper.loop(Looper.java:164)
                                                                             at android.app.ActivityThread.main(ActivityThread.java:6494)
                                                                             at java.lang.reflect.Method.invoke(Native Method)
                                                                             at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
                                                                             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
                                                                          Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'io.reactivex.Observable com.example.viewmodel.MovieViewModel.discoverMovies(java.lang.String)' on a null object reference
                                                                             at com.example.fragment.MoviesFragment.moviesSubscription(MoviesFragment.java:119)
                                                                             at com.example.fragment.MoviesFragment.onResume(MoviesFragment.java:146)
                                                                             at android.support.v4.app.Fragment.performResume(Fragment.java:2308)
                                                                             at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1465)
                                                                             at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1750)
                                                                             at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1819)
                                                                             at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3227)
                                                                             at android.support.v4.app.FragmentManagerImpl.dispatchResume(FragmentManager.java:3191)
                                                                             at android.support.v4.app.FragmentController.dispatchResume(FragmentController.java:214)
                                                                             at android.support.v4.app.FragmentActivity.onResumeFragments(FragmentActivity.java:482)
                                                                             at android.support.v4.app.FragmentActivity.onPostResume(FragmentActivity.java:471)
                                                                             at android.support.v7.app.AppCompatActivity.onPostResume(AppCompatActivity.java:171)
                                                                             at android.app.Activity.performResume(Activity.java:7131)
                                                                             at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3556)
                                                                             at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3621) 
                                                                             at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2862) 
                                                                             at android.app.ActivityThread.-wrap11(Unknown Source:0) 
                                                                             at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589) 
                                                                             at android.os.Handler.dispatchMessage(Handler.java:106) 
                                                                             at android.os.Looper.loop(Looper.java:164) 
                                                                             at android.app.ActivityThread.main(ActivityThread.java:6494) 
                                                                             at java.lang.reflect.Method.invoke(Native Method) 
                                                                             at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) 
                                                                             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807) 

我已经定义了视图模型和viewmodelimpl,如下所示:

public interface MovieViewModel {
    Observable<MovieResponse> discoverMovies(String apiKey);
}

public class MovieViewModelImpl implements MovieViewModel {

    private MovieAPI movieAPI;

    @Inject
    MovieViewModelImpl(MovieAPI movieAPI) {
        this.movieAPI = movieAPI;
    }

    @Override
    public Observable<MovieResponse> discoverMovies(String apiKey) {
        return movieAPI.discoverMovies(apiKey);
    }
}

public interface MovieAPI {

    Observable<MovieResponse> discoverMovies(String apiKey);
}

这是一个电影服务,它有一个Query来获取获取电影所需的api Key。基本URL正在使用OkHttp3构建并在服务工厂类中进行改造。

public interface MovieService {

@Headers("Accept:application/json")
@GET("movie/popular")
Observable<MovieResponse> discoverMovies(@Query("api_key") String apiKey);

}

我有一个MovieViewModelModule,使用@Module (includes = MovieViewModelModule.class)在AppModule中注入。

@Module(includes = {MovieAPIModule.class})
public class MovieViewModelModule {

    @Provides
    MovieViewModel provideMovieViewModel(MovieAPI movieAPI) {
        return new MovieViewModelImpl(movieAPI);
    }
}

回购:赌场

答案

您缺少在https://github.com/mchapagai/Discover-Movies中实际注入字段的代码。

你需要一个fragment接口才能做到这一点,假设它的名字是MoviesComponent

  • 使用Component创建界面ann annotate it
  • 在界面中创建方法@Component
  • 在onCreateView()中,使用inject(MoviesFragment fragment)注入视图模型字段,确保为要生成的此类构建项目。

在该注入行之后,将注入您的视图模型字段,您可以使用它。

以上是关于Dagger MVVM - ViewModel注入为null的主要内容,如果未能解决你的问题,请参考以下文章

ViewModel 中的 Kotlin Dagger 字段注入引发 Dagger/Binding 异常

Kotlin dagger 2 Android ViewModel 注入错误

将依赖项注入ViewModel时的Dagger / MissingBinding

Dagger2下的ViewModel

Dagger 2:在片段中调用onAttach之前,注入的对象可能仍为null

没有Dagger2的Android Kotlin MVVM结构