如何将数据从Activity或Fragment传递到ViewModel?

3

我正在创建一个项目,使用themoviedb API获取数据。为此,我正在使用MVVM架构。从MovieListFragment,我想将类别(例如热门,最高评分)传递给MovieViewModel以根据此来筛选电影,但是我得到了空值。

以下是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;
    }
}

以下是 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;
    }
}

我遇到了这样的错误:-
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)

我不知道为什么在你的情况下它不起作用,但你的问题是我的问题的答案。在我的项目中它运行良好。谢谢。 - Rucha Bhatt Joshi
3个回答

1

由于电影视图模型的构造函数在setter之前读取Category,因此它始终为空。

那么作为方法参数的类别呢?

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

如果需要更详细的实现,需要一个仓库类。

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


0

如果您在movieViewModel.setCategory(category);这一行中的字符串category获取到了null值,那么这意味着MovieListFragment中的category字段为空。

请检查是否已经在fragment上调用了setCategory(String category)方法。

如果不是这种情况,请详细说明错误。例如,它发生在哪一行等。


0
在MovieListFragment类中:
首先删除这一行:movieViewModel.setCategory(category); 然后在这里传递“category”: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);
                    }
                });
            }
        });

在 MovieViewModel 类中:

将此行代码移至 getMoviesRepository(String category) 方法内:listOfMovies = repository.getListOfMovies(category, API_KEY);

然后从 MovieViewModel 类中删除 category 变量和 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;
    }

}

如何创建“repository”? - CoolMind
仓储类就像模型类一样,但它使用DAO接口从离线房间数据库获取和设置数据,并且也可以从在线服务器获取和设置数据。 我找不到一个好的简单Java示例,但看看GitHub中的这个简单项目。他们使用远程和本地存储库。 https://github.com/segunfamisa/android-mvvm-sample/tree/master/app/src/main/java/com/segunfamisa/sample/mvvm/data/repository - J-Abdo
谢谢您提供详细的答案!是的,我明白它可以是一个Room数据库。我的意思是,它是如何创建的(例如repository = new ...)?因为我们没有直接在MovieViewModel中传递repository(我也看不到它是如何创建的)。这不是您代码的问题,而是作者和所有回复者的问题。 - CoolMind

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接