我目前正致力于创建一个应用程序,该应用程序将向最终用户显示当前电影海报的网格。我使用TheMovieDB API获取电影数据,并使用ASync任务在应用程序中获取数据。我希望最终能够在我的应用程序中实现分页,其中向用户显示准无限的电影海报网格。
因此,我接近这个的方式是我创建了我的Movie
模型对象,它将存储关于每部电影的一些数据。然后,当我从API中提取数据时,我会填充ArrayList
个完整的电影对象。但是,我不确定一旦实现分页,将创建多少部电影。为了安全起见,我已将ArrayList
初始化为不包含任何电影。我的ASync任务完成后(如在onPostExecute()
中),我将所有电影附加到我的阵列。
我现在面临的问题是,在onPostExecute()
的任务中,我认为notifyDataSetChanged()
会给我一个电影海报网格。但是,情况似乎并非如此。我不确定为什么,但我必须用我新添加的数组重新创建适配器,以便海报显示在屏幕上。我在onPostExecute()
中重新创建适配器的唯一原因是因为我在网上的其他地方看到了它,但没有完全理解为什么使用它。
以下是我正在使用的代码:
package com.example.android.popularmovies_stage1;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import java.util.List;
public class MovieSelection extends AppCompatActivity {
RecyclerView mRecyclerView;
MovieAdapter mAdapter;
List<Movie> mMoviesList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_movie_selection);
mRecyclerView = (RecyclerView) findViewById(R.id.rv_movie_selection);
GridLayoutManager layoutManager = new GridLayoutManager(getApplicationContext(), 3);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setHasFixedSize(true);
mAdapter = new MovieAdapter(mMoviesList);
mRecyclerView.setAdapter(mAdapter);
new FetchMoviesTask().execute();
}
private class MovieAdapter extends RecyclerView.Adapter<MovieHolder>{
private List<Movie> adapterMovies;
public MovieAdapter(List<Movie> movies){
adapterMovies = movies;
}
@Override
public MovieHolder onCreateViewHolder(ViewGroup viewGroup, int viewType){
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
View view = inflater.inflate(R.layout.movie_list_item, viewGroup, false);
return new MovieHolder(view);
}
@Override
public void onBindViewHolder(MovieHolder holder, int position){
Movie currentMovie = adapterMovies.get(position);
Picasso.with(getApplicationContext())
.load("https://image.tmdb.org/t/p/w185/" + currentMovie.getPosterPath())
.into(holder.holderImageView);
}
@Override
public int getItemCount(){
return adapterMovies.size();
}
}
private class MovieHolder extends RecyclerView.ViewHolder{
ImageView holderImageView;
public MovieHolder(View movieView){
super(movieView);
holderImageView = (ImageView) movieView.findViewById(R.id.list_item_image_view);
}
}
private class FetchMoviesTask extends AsyncTask<Void, Void, List<Movie>>{
@Override
protected List<Movie> doInBackground(Void... params){
return new MovieFetcher().fetchMovies();
}
@Override
protected void onPostExecute(List<Movie> parsedMovies){
mMoviesList = parsedMovies;
// mAdapter.notifyDataSetChanged(); Unsure of why this is not working as I expected?
mAdapter = new MovieAdapter(mMoviesList);
mRecyclerView.setAdapter(mAdapter);
}
}
}
为什么notifyDataSetChanged()
方法不能按预期工作?如果在没有任何数据的情况下初始化ArrayList
,为什么必须重新创建我的适配器?当然,非常感谢对此问题的任何帮助!
答案 0 :(得分:2)
您正在更改适配器所持有的ListView的引用。
// New reference which is causing issue, use .addAll() property of ArrayList.
mMoviesList = parsedMovies;
在postExecute() -
中更新您的代码@Override
protected void onPostExecute(List<Movie> parsedMovies){
mMoviesList.addAll(parsedMovies);
// Now I am sure this will work :)
mAdapter.notifyDataSetChanged();
}
原因 - 您的新MovieFetcher().fetchMovies()
必须在postExecute中创建新的ArrayList
,并且如果您将新的ArrayList分配给传递给Adapter的新列表你的ListView然后引用被更改,你的适配器将不会监听更新(notifyDataSetChanged),因为你的数据集没有改变,只有参考被更改。
答案 1 :(得分:1)
@Override
protected void onPostExecute(List<Movie> parsedMovies){
mMoviesList.add(parsedMovies);
mAdapter.notifyDataSetChanged();
}
答案 2 :(得分:1)
在将适配器设置到RecyclerView之前,您应该调用notifyDataSetChanged()方法。
像:
private class FetchMoviesTask extends AsyncTask<Void, Void, List<Movie>>{
@Override
protected List<Movie> doInBackground(Void... params){
return new MovieFetcher().fetchMovies();
}
@Override
protected void onPostExecute(List<Movie> parsedMovies){
mMoviesList = parsedMovies;
mAdapter = new MovieAdapter(mMoviesList);
mRecyclerView.setAdapter(mAdapter);
mAdapter.notifyDataSetChanged();
}
}
答案 3 :(得分:1)
在onPostExecute()中添加以下行
mMoviesList = parsedMovies;
表示mMoviesList
创建新实例,因此mAdapter.notifyDataSetChanged();
无效。
使用以下代码
private class FetchMoviesTask extends AsyncTask<Void, Void, List<Movie>>{
@Override
protected List<Movie> doInBackground(Void... params){
return new MovieFetcher().fetchMovies();
}
@Override
protected void onPostExecute(List<Movie> parsedMovies){
// mMoviesList.clear();// If you want clear existing data add this line, otherwise remove it
if(parsedMovies != null){
mMoviesList.addAll(parsedMovies);
}
mAdapter.notifyDataSetChanged(); Unsure of why this is not working as I expected?
} //end of onPostExecute
} //end of FetchMoviesTask
供参考check here