Java 何时为RecyclerView创建新适配器-notifyDataSet()不工作?

Java 何时为RecyclerView创建新适配器-notifyDataSet()不工作?,java,android,android-recyclerview,Java,Android,Android Recyclerview,我目前正在创建一个应用程序,它将向最终用户显示当前电影海报的网格。我使用API获取电影数据,数据在应用程序中使用异步任务获取。我希望最终能够在我的应用程序中实现分页,在应用程序中,用户可以看到一个近乎无限的电影海报网格 因此,我的方法是创建我的电影模型对象,它将存储关于每部电影的一些数据。然后,当我从API中提取数据时,我会在ArrayList中填充电影对象。但是,我不确定在实现分页后将创建多少部电影。为了安全起见,我已经初始化了我的ArrayList,使其不包含任何电影。异步任务完成后(如中的

我目前正在创建一个应用程序,它将向最终用户显示当前电影海报的网格。我使用API获取电影数据,数据在应用程序中使用异步任务获取。我希望最终能够在我的应用程序中实现分页,在应用程序中,用户可以看到一个近乎无限的电影海报网格

因此,我的方法是创建我的
电影
模型对象,它将存储关于每部电影的一些数据。然后,当我从API中提取数据时,我会在
ArrayList
中填充电影对象。但是,我不确定在实现分页后将创建多少部电影。为了安全起见,我已经初始化了我的
ArrayList
,使其不包含任何电影。异步任务完成后(如中的
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);
        }
    }
}
package com.example.android.popularmovies_stage1;
导入android.os.AsyncTask;
导入android.os.Bundle;
导入android.support.v7.app.AppActivity;
导入android.support.v7.widget.GridLayoutManager;
导入android.support.v7.widget.RecyclerView;
导入android.view.LayoutInflater;
导入android.view.view;
导入android.view.ViewGroup;
导入android.widget.ImageView;
导入com.squareup.picasso.picasso;
导入java.util.ArrayList;
导入java.util.List;
公共类电影选举活动{
回收视图mRecyclerView;
电影配接器;
List mMoviesList=newarraylist();
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity\u movie\u selection);
mRecyclerView=(RecyclerView)findViewById(R.id.rv\u movie\u selection);
GridLayoutManager layoutManager=新的GridLayoutManager(getApplicationContext(),3);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setHasFixedSize(true);
mAdapter=新电影适配器(mMoviesList);
mRecyclerView.setAdapter(mAdapter);
新建FetchMoviesTask().execute();
}
私有类MovieAdapter扩展了RecyclerView.Adapter{
私有列表适配器移动;
公共电影适配器(列出电影){
adapterMovies=电影;
}
@凌驾
public MovieHolder onCreateViewHolder(视图组视图组,int视图类型){
LayoutInflater充气器=LayoutInflater.from(viewGroup.getContext());
视图=充气机。充气(R.layout.movie\u list\u项,视图组,false);
归还新的电影持有人(视图);
}
@凌驾
BindViewHolder上的公共无效(电影持有人,内部位置){
Movie currentMovie=adapterMovies.get(位置);
Picasso.with(getApplicationContext())
.加载(“https://image.tmdb.org/t/p/w185/“+currentMovie.getPosterPath())
.进入(支架。支架图像视图);
}
@凌驾
public int getItemCount(){
返回adapterMovies.size();
}
}
私有类MovieHolder扩展了RecyclerView.ViewHolder{
图像视图持有者图像视图;
公众电影持有人(查看电影视图){
超级(影视界);;
holderImageView=(ImageView)movieView.findViewById(R.id.list\u item\u image\u view);
}
}
私有类FetchMoviesTask扩展了AsyncTask{
@凌驾
受保护列表doInBackground(无效…参数){
返回新的MovieFetcher().fetchMovies();
}
@凌驾
受保护的void onPostExecute(列出已解析的移动){
mMoviesList=parsedMovies;
//mAdapter.notifyDataSetChanged();不确定这为什么不能像我预期的那样工作?
mAdapter=新电影适配器(mMoviesList);
mRecyclerView.setAdapter(mAdapter);
}
}
}

为什么
notifyDataSetChanged()
方法不能按预期工作?如果
ArrayList
在没有任何数据的情况下初始化,为什么我必须重新创建适配器?当然,在此问题上的任何帮助都将不胜感激

您正在更改适配器持有的ListView的引用

// New reference which is causing issue, use .addAll() property of ArrayList.
mMoviesList = parsedMovies;     
更新postExecute()中的代码-

@覆盖
受保护的void onPostExecute(列出已解析的移动){
mMoviesList.addAll(解析视频);
//现在我确信这会奏效:)
mAdapter.notifyDataSetChanged();
}
原因-您的新的
MovieFetcher().fetchMovies()
必须在其中创建新的
ArrayList
,并在postExecute中返回,如果您将该新的ArrayList分配给传递给ListView适配器的列表,则引用将被更改,并且适配器将不会侦听更新(notifyDataSetChanged),因为您的数据集没有更改,所以只更改了引用。

@Override
@Override
    protected void onPostExecute(List<Movie> parsedMovies){
        mMoviesList.add(parsedMovies);
        mAdapter.notifyDataSetChanged(); 
    }
受保护的void onPostExecute(列出已解析的移动){ mMoviesList.add(解析视频); mAdapter.notifyDataSetChanged(); }
您应该在将适配器设置为RecyclerView之后而不是之前调用notifyDataSetChanged()方法

比如:

私有类FetchMoviesTask扩展了AsyncTask{
@凌驾
受保护列表doInBackground(无效…参数){
返回新的MovieFetcher().fetchMovies();
}
@凌驾
保护空隙
@Override
    protected void onPostExecute(List<Movie> parsedMovies){
        mMoviesList.add(parsedMovies);
        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 = parsedMovies;
        mAdapter = new MovieAdapter(mMoviesList);
        mRecyclerView.setAdapter(mAdapter);
        mAdapter.notifyDataSetChanged();
    }
}
 mMoviesList = parsedMovies;
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