简体   繁体   English

如何将数据从活动或片段传递到视图模型?

[英]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.我正在创建一个项目,在该项目中我使用 themoviedb api 来获取数据。 For this I am using MVVM architecture.为此,我使用 MVVM 架构。 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.从 MovieListFragment ,我想将诸如流行、top_rated 之类的类别传递给 MovieViewModel 以相应地过滤电影,但我得到的是空值。

Here is MovieListFragment class :-这是 MovieListFragment 类:-

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 :-这是 MovieViewModel 类:-

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)

If you are getting null value for the string category in line movieViewModel.setCategory(category);如果您在movieViewModel.setCategory(category);行中获得字符串category nullmovieViewModel.setCategory(category); , it means the field category of MovieListFragment is null. ,表示MovieListFragment的字段category为空。

Try checking if you have invoked the setCategory(String category) method on the fragment .尝试检查您是否在fragment上调用了setCategory(String category)方法。

If that's not the case, please elaborate on the error.如果不是这种情况,请详细说明错误。 Eg on which line it occurs etc.例如它发生在哪条线上等等。

Since the Category is read by the constructor of MovieViewModel before the setter, it is always null.由于 Category 在 setter 之前由 MovieViewModel 的构造函数读取,因此它始终为 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文档: https : //developer.android.com/topic/libraries/architecture/viewmodel

You have to create viewmodel factory to pass data to viewmodel from activity or fragment.您必须创建视图模型工厂才能将数据从活动或片段传递给视图模型。 You can refer this at here .您可以在此处参考。

In MovieListFragment class:在 MovieListFragment 类中:

First delete this line: movieViewModel.setCategory(category);首先删除这一行: movieViewModel.setCategory(category);

And pass "category" here: movieViewModel.getMoviesRepository(category) like code below:并在此处传递“类别”: movieViewModel.getMoviesRepository(category)如下代码:

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:在 MovieViewModel 类中:

Move this line inside getMoviesRepository(String category) listOfMovies = repository.getListOfMovies(category, API_KEY);将这一行移到 getMoviesRepository(String category) listOfMovies = repository.getListOfMovies(category, API_KEY);

And just remove category variable and setCategory() method from MovieViewModel class like this:只需从MovieViewModel类中删除类别变量和setCategory()方法,如下所示:

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;
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM