2017-12-16 18 views
0

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

答えて

1

あなたが実際にfragmentのフィールドを注入するコードが欠落しています。

は、あなたがそれを行うためにComponentインタフェースを必要とする、のは、その名前が

  • MoviesComponent

    あるとしましょう)(アンはあなたのインターフェイスであなたのonCreateViewで
  • の方法inject(MoviesFragment fragment)を作成@Component
  • でそれに注釈を付けるインタフェースを作成し、 DaggerMoviesComponent.builder().build().inject(this)を使用してビューモデルフィールドを挿入し、このクラスが生成されるようにプロジェクトを構築してください。

この注入線の後に、あなたのビューモデルフィールドが注入され、それを使用することができます。

+0

私は、AppModuleに含まれているInjectorsModuleにフラグメントを注入しているInjectorModulesを持っています。私はgithubリンクも提供しました。 – Ronan