Dagger2を使用してフラグメントにViewModelを注入しようとしていますが、NullPointerException
が表示されています。以下は、フラグメントとスタックトレースです。Dagger MVVM - ViewModel注入がnullの場合
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);
}
は映画をフェッチするために必要なAPIキーを取得するためのクエリを持っている映画サービスです。ベースURLはOkHttp3を使用して構築されており、サービスファクトリクラスで改造されています。
パブリックインターフェイスMovieService {
@Headers("Accept:application/json")
@GET("movie/popular")
Observable<MovieResponse> discoverMovies(@Query("api_key") String apiKey);
}
Iは@Module (includes = MovieViewModelModule.class)
を用いAppModuleに注入さMovieViewModelModuleを有します。
@Module(includes = {MovieAPIModule.class})
public class MovieViewModelModule {
@Provides
MovieViewModel provideMovieViewModel(MovieAPI movieAPI) {
return new MovieViewModelImpl(movieAPI);
}
}
レポ:https://github.com/mchapagai/Discover-Movies
私は、AppModuleに含まれているInjectorsModuleにフラグメントを注入しているInjectorModulesを持っています。私はgithubリンクも提供しました。 – Ronan