Rockers Devil
Rockers Devil

Reputation: 31

How to pass data from activity or fragment to viewmodel?

I am creating a project in which i am using themoviedb api to fetch data. For this I am using MVVM architecture. From MovieListFragment , I want to pass category such as popular, top_rated to MovieViewModel for filtering the movies accordingly , but there i am getting null value.

Here is MovieListFragment class :-

public class MovieListFragment extends Fragment {

    private MovieViewModel movieViewModel;
    private static final String BASE_URL = "https://api.themoviedb.org";
    private static final String API_KEY = "API_KEY";
    private String category;

    private GridView gridView;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_movie_list, container, false);
        gridView = rootView.findViewById(R.id.images_grid_view);

        movieViewModel = ViewModelProviders.of(this).get(MovieViewModel.class);
        movieViewModel.setCategory(category);  // from here i am passing value
        movieViewModel.getMoviesRepository().observe(getActivity(), new Observer<MovieResults>() {  // error line no :- 76
                @Override
                public void onChanged(MovieResults movieResults) {
                    final List<MovieResults.ResultsBean> listOfMovies = movieResults.getResults();  // error line no :- 79

                    MovieListAdapter mAdapter = new MovieListAdapter(getContext(), listOfMovies);
                    gridView.setAdapter(mAdapter);
                    gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                        @Override
                        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                            mCallback.onImageSelected(position, listOfMovies);
                        }
                    });
                }
            });
        return rootView;
    }

    public void setCategory(String category) {
        this.category = category;
    }
}

Here is MovieViewModel class :-

public class MovieViewModel extends AndroidViewModel {
    private String category;
    private static final String API_KEY = "api_key";
    private MovieRepository repository;
    private MutableLiveData<MovieResults> listOfMovies;

    public MovieViewModel(@NonNull Application application) {
        super(application);
        Log.d("MovieViewModel", category); // but here i am getting null value
        listOfMovies = repository.getListOfMovies(category, API_KEY);
    }

    public MutableLiveData<MovieResults> getMoviesRepository() {
        return listOfMovies;
    }

    public void setCategory(String category) {
        this.category = category;
    }
}

I am getting error like this :-

java.lang.NullPointerException: Attempt to invoke virtual method 'java.util.List com.mountblue.moviesapp.entity.MovieResults.getResults()' on a null object reference
        at com.mountblue.moviesapp.fragment.MovieListFragment$2.onChanged(MovieListFragment.java:79)
        at com.mountblue.moviesapp.fragment.MovieListFragment$2.onChanged(MovieListFragment.java:76)

Upvotes: 3

Views: 14733

Answers (3)

Bonnjalal
Bonnjalal

Reputation: 76

In MovieListFragment class:

First delete this line: movieViewModel.setCategory(category);

And pass "category" here: movieViewModel.getMoviesRepository(category) like code below:

movieViewModel.getMoviesRepository(category).observe(getActivity(), new Observer<MovieResults>() {  // error line no :- 76
            @Override
            public void onChanged(MovieResults movieResults) {
                final List<MovieResults.ResultsBean> listOfMovies = movieResults.getResults();  // error line no :- 79

                MovieListAdapter mAdapter = new MovieListAdapter(getContext(), listOfMovies);
                gridView.setAdapter(mAdapter);
                gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                    @Override
                    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                        mCallback.onImageSelected(position, listOfMovies);
                    }
                });
            }
        });

In MovieViewModel class:

Move this line inside getMoviesRepository(String category) listOfMovies = repository.getListOfMovies(category, API_KEY);

And just remove category variable and setCategory() method from MovieViewModel class like this:

public class MovieViewModel extends AndroidViewModel {
    
    private static final String API_KEY = "api_key";
    private MovieRepository repository;
    private MutableLiveData<MovieResults> listOfMovies;

    public MovieViewModel(@NonNull Application application) {
        super(application);
        
    }

    public MutableLiveData<MovieResults> getMoviesRepository(String category) {
        Log.d("MovieViewModel", category); // but here i am getting null value
        listOfMovies = repository.getListOfMovies(category, API_KEY);
        return listOfMovies;
    }

}

Upvotes: 0

ysys
ysys

Reputation: 72

Since the Category is read by the constructor of MovieViewModel before the setter, it is always null.

What about category as method arguments?

public class MovieViewModel extends AndroidViewModel {

    private static final String API_KEY = "api_key";
    private MovieRepository repository;
    private MutableLiveData<MovieResults> listOfMovies = new MutableLiveData<MovieResults>();

    public MovieViewModel(@NonNull Application application) {
        super(application);
    }

    public MutableLiveData<MovieResults> getMoviesRepository(category) {
        loadData(category);
        return listOfMovies;
    }

    private void loadData(category) {
        // Do an asynchronous operation to fetch MovieResults.
        repository.getListOfMovies(category, API_KEY);

        ...
        // Receive asynchronous result in callback

        // Post the result after getting the asynchronous result.
        listOfMovies.postValue(response)
    }
}

For a more detailed implementation, need a repository class.

Documents: https://developer.android.com/topic/libraries/architecture/viewmodel

Upvotes: 0

tykimseoul
tykimseoul

Reputation: 108

If you are getting null value for the string category in line movieViewModel.setCategory(category);, it means the field category of MovieListFragment is null.

Try checking if you have invoked the setCategory(String category) method on the fragment.

If that's not the case, please elaborate on the error. E.g. on which line it occurs etc.

Upvotes: 0

Related Questions