notifyDataSetChanged不能在RecyclerView上工作

我从服务器获取数据,然后parsing并将其存储在列表中。 我使用RecyclerView的适配器的这个列表。 我正在使用片段。

我正在用KitKat使用Nexus 5。 我正在使用支持库。 这会有所作为吗?

这里是我的代码:(使用虚拟数据的问题)

成员variables:

List<Business> mBusinesses = new ArrayList<Business>(); RecyclerView recyclerView; RecyclerView.LayoutManager mLayoutManager; BusinessAdapter mBusinessAdapter; 

我的onCreateView()

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Getting data from server getBusinessesDataFromServer(); View view = inflater.inflate(R.layout.fragment_business_list, container, false); recyclerView = (RecyclerView) view .findViewById(R.id.business_recycler_view); recyclerView.setHasFixedSize(true); mLayoutManager = new LinearLayoutManager(getActivity()); recyclerView.setLayoutManager(mLayoutManager); mBusinessAdapter = new BusinessAdapter(mBusinesses); recyclerView.setAdapter(mBusinessAdapter); return view; } 

从服务器获取数据后,调用parseResponse()

 protected void parseResponse(JSONArray response, String url) { // insert dummy data for demo mBusinesses.clear(); Business business; business = new Business(); business.setName("Google"); business.setDescription("Google HeadQuaters"); mBusinesses.add(business); business = new Business(); business.setName("Yahoo"); business.setDescription("Yahoo HeadQuaters"); mBusinesses.add(business); business = new Business(); business.setName("Microsoft"); business.setDescription("Microsoft HeadQuaters"); mBusinesses.add(business); Log.d(Const.DEBUG, "Dummy Data Inserted\nBusinesses Length: " + mBusinesses.size()); mBusinessAdapter = new BusinessAdapter(mBusinesses); mBusinessAdapter.notifyDataSetChanged(); } 

我的商家:

 public class BusinessAdapter extends RecyclerView.Adapter<BusinessAdapter.ViewHolder> { private List<Business> mBusinesses = new ArrayList<Business>(); // Provide a reference to the type of views that you are using // (custom viewholder) public static class ViewHolder extends RecyclerView.ViewHolder { public TextView mTextViewName; public TextView mTextViewDescription; public ImageView mImageViewLogo; public ViewHolder(View v) { super(v); mTextViewName = (TextView) v .findViewById(R.id.textView_company_name); mTextViewDescription = (TextView) v .findViewById(R.id.textView_company_description); mImageViewLogo = (ImageView) v .findViewById(R.id.imageView_company_logo); } } // Provide a suitable constructor (depends on the kind of dataset) public BusinessAdapter(List<Business> myBusinesses) { Log.d(Const.DEBUG, "BusinessAdapter -> constructor"); mBusinesses = myBusinesses; } // Create new views (invoked by the layout manager) @Override public BusinessAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { Log.d(Const.DEBUG, "BusinessAdapter -> onCreateViewHolder()"); // create a new view View v = LayoutInflater.from(parent.getContext()).inflate( R.layout.item_business_list, parent, false); ViewHolder vh = new ViewHolder(v); return vh; } // Replace the contents of a view (invoked by the layout manager) @Override public void onBindViewHolder(ViewHolder holder, int position) { // - get element from your dataset at this position // - replace the contents of the view with that element Log.d(Const.DEBUG, "BusinessAdapter -> onBindViewHolder()"); Business item = mBusinesses.get(position); holder.mTextViewName.setText(item.getName()); holder.mTextViewDescription.setText(item.getDescription()); holder.mImageViewLogo.setImageResource(R.drawable.ic_launcher); } // Return the size of your dataset (invoked by the layout manager) @Override public int getItemCount() { Log.d(Const.DEBUG, "BusinessAdapter -> getItemCount()"); if (mBusinesses != null) { Log.d(Const.DEBUG, "mBusinesses Count: " + mBusinesses.size()); return mBusinesses.size(); } return 0; } } 

但是我没有看到在视图中显示的数据。 我究竟做错了什么?

这是我的日志,

 07-14 21:15:35.669: D/xxx(2259): Dummy Data Inserted 07-14 21:15:35.669: D/xxx(2259): Businesses Length: 3 07-14 21:26:26.969: D/xxx(2732): BusinessAdapter -> constructor 

在这之后我没有得到任何日志。 不应该再次调用适配器中的getItemCount()吗?

在你的parseResponse()你正在创build一个BusinessAdapter类的新实例,但是实际上你并没有在任何地方使用它,所以你的RecyclerView并不知道新的实例存在。

您或者需要:

  • 再次调用recyclerView.setAdapter(mBusinessAdapter)以更新RecyclerView的适配器引用以指向新的
  • 或者只是删除mBusinessAdapter = new BusinessAdapter(mBusinesses); 继续使用现有的适配器。 由于您尚未更改mBusinesses引用,所以适配器仍将使用该数组列表,并且在调用notifyDataSetChanged()时应该正确更新。

试试这个方法:

 List<Business> mBusinesses2 = mBusinesses; mBusinesses.clear(); mBusinesses.addAll(mBusinesses2); //and do the notification 

有点费时,但是它应该工作。

我有同样的问题。 我只是在类的onCreate之前声明adapter public来解决它。

 PostAdapter postAdapter; 

之后

 postAdapter = new PostAdapter(getActivity(), posts); recList.setAdapter(postAdapter); 

最后我打电话给:

 @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); // Display the size of your ArrayList Log.i("TAG", "Size : " + posts.size()); progressBar.setVisibility(View.GONE); postAdapter.notifyDataSetChanged(); } 

愿这能帮助你。

只是为了补充其他答案,因为我不认为有人在这里提到这个: notifyDataSetChanged() 应该在主线程上执行 notifyDataSetChanged() 也可以 notify<Something> RecyclerView.Adapter notify<Something>方法)

从我所收集的内容来看,由于您在同一个块中有parsing过程和对notifyDataSetChanged()的调用, notifyDataSetChanged()要么从工作线程调用它,要么在主线程上执行JSONparsing(这也是否定的不,因为我相信你知道)。 所以正确的方法是:

 protected void parseResponse(JSONArray response, String url) { // insert dummy data for demo // <yadda yadda yadda> mBusinessAdapter = new BusinessAdapter(mBusinesses); // or just use recyclerView.post() or [Fragment]getView().post() // instead, but make sure views haven't been destroyed while you were // parsing new Handler(Looper.getMainLooper()).post(new Runnable() { public void run() { mBusinessAdapter.notifyDataSetChanged(); } }); 

}

PS奇怪的是,我不认为你从IDE或运行时日志得到有关主线程的任何迹象。 这只是从我个人的观察:如果我从工作者线程调用notifyDataSetChanged() ,我没有得到强制性只有创build一个视图层次结构的原始线程可以触摸它的视图消息或类似的东西 – 它只是失败(在我的情况下,一个脱离主线程调用甚至可以防止后续的主线程调用正常运行,可能是由于某种竞争条件)

此外, RecyclerView.Adapter API参考和相关的官方开发指南都没有明确提及目前的主线程要求(现在是2017年),Android Studio皮棉检测规则也没有涉及到这个问题。

但是, 这是作者自己对此的解释