The application’s PagerAdapter changed the adapter’s contents without calling PagerAdapter#notifyDataSetChanged

今天开发的时候遇到如题所述的异常,找了一下在satckoverflow上看到一个比较靠谱的答案:

After ADT 22 the PagerAdapter has gotten very strict about calling notifyDataSetChanged() before calling getCount(). It evidently keeps track of what it thinks the count should be and if this is not the same as what getCount() returns it throws this exception. So the solution is simply to call notifyDataSetChanged() on the adapter every time the size of the data changes.

在adt22之后,PagerAdapter对于notifyDataSetChanged()和getCount()的执行顺序是非常严格的,系统跟踪count的值,如果这个值和getCount返回的值不一致,就会抛出这个异常。所以为了保证getCount总是返回一个正确的值,那么在初始化ViewPager时,应先给Adapter初始化内容后再将该adapter传给ViewPager,如果不这样处理,在更新adapter的内容后,应该调用一下adapter的notifyDataSetChanged方法。

在初始化ViewPager时,应先给Adapter初始化内容后再将该adapter传给ViewPager,如果不这样处理,在更新adapter的内容后,应该调用一下adapter的notifyDataSetChanged方法,否则在ADT22以上使用会报The application’s PagerAdapter changed the adapter’s contents without calling PagerAdapter#notifyDataSetChanged的异常,具体原因可参考:http://stackoverflow.com/questions/16756131/fragmentstatepageradapter-stopped-working-after-updating-to-adt-22

package com.itheima.zhbj52.base;import java.util.ArrayList;import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.os.Handler;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.text.TextUtils;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.TextView;
import android.widget.Toast;import com.google.gson.Gson;
import com.itheima.zhbj52.NewsDetailActivity;
import com.itheima.zhbj52.R;
import com.itheima.zhbj52.domain.NewsData.NewsTabData;
import com.itheima.zhbj52.domain.TabData;
import com.itheima.zhbj52.domain.TabData.TabNewsData;
import com.itheima.zhbj52.domain.TabData.TopNewsData;
import com.itheima.zhbj52.global.GlobalContants;
import com.itheima.zhbj52.utils.CacheUtils;
import com.itheima.zhbj52.utils.PrefUtils;
import com.itheima.zhbj52.utils.bitmap.MyBitmapUtils;
import com.itheima.zhbj52.view.RefreshListView;
import com.itheima.zhbj52.view.RefreshListView.OnRefreshListener;
import com.lidroid.xutils.BitmapUtils;
import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.ViewUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;
import com.lidroid.xutils.http.client.HttpRequest.HttpMethod;
import com.lidroid.xutils.view.annotation.ViewInject;
import com.viewpagerindicator.CirclePageIndicator;/*** 页签详情页* * @author Kevin* */
public class TabDetailPager extends BaseMenuDetailPager implementsOnPageChangeListener {NewsTabData mTabData;private TextView tvText;private String mUrl;private TabData mTabDetailData;@ViewInject(R.id.vp_news)private ViewPager mViewPager;@ViewInject(R.id.tv_title)private TextView tvTitle;// 头条新闻的标题private ArrayList<TopNewsData> mTopNewsList;// 头条新闻数据集合@ViewInject(R.id.indicator)private CirclePageIndicator mIndicator;// 头条新闻位置指示器@ViewInject(R.id.lv_list)private RefreshListView lvList;// 新闻列表private ArrayList<TabNewsData> mNewsList; // 新闻数据集合private NewsAdapter mNewsAdapter;private String mMoreUrl;// 更多页面的地址private Handler mHandler;public TabDetailPager(Activity activity, NewsTabData newsTabData) {super(activity);mTabData = newsTabData;mUrl = GlobalContants.SERVER_URL + mTabData.url;}@Overridepublic View initViews() {View view = View.inflate(mActivity, R.layout.tab_detail_pager, null);// 加载头布局View headerView = View.inflate(mActivity, R.layout.list_header_topnews,null);ViewUtils.inject(this, view);ViewUtils.inject(this, headerView);// 将头条新闻以头布局的形式加给listviewlvList.addHeaderView(headerView);// 设置下拉刷新监听lvList.setOnRefreshListener(new OnRefreshListener() {@Overridepublic void onRefresh() {getDataFromServer();}@Overridepublic void onLoadMore() {if (mMoreUrl != null) {getMoreDataFromServer();} else {Toast.makeText(mActivity, "最后一页了", Toast.LENGTH_SHORT).show();lvList.onRefreshComplete(false);// 收起加载更多的布局}}});lvList.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view,int position, long id) {System.out.println("被点击:" + position);// 35311,34221,34234,34342// 在本地记录已读状态String ids = PrefUtils.getString(mActivity, "read_ids", "");String readId = mNewsList.get(position).id;if (!ids.contains(readId)) {ids = ids + readId + ",";PrefUtils.setString(mActivity, "read_ids", ids);}// mNewsAdapter.notifyDataSetChanged();changeReadState(view);// 实现局部界面刷新, 这个view就是被点击的item布局对象// 跳转新闻详情页Intent intent = new Intent();intent.setClass(mActivity, NewsDetailActivity.class);intent.putExtra("url", mNewsList.get(position).url);mActivity.startActivity(intent);}});return view;}/*** 改变已读新闻的颜色*/private void changeReadState(View view) {TextView tvTitle = (TextView) view.findViewById(R.id.tv_title);tvTitle.setTextColor(Color.GRAY);}@Overridepublic void initData() {String cache = CacheUtils.getCache(mUrl, mActivity);if (!TextUtils.isEmpty(cache)) {parseData(cache, false);}getDataFromServer();}private void getDataFromServer() {HttpUtils utils = new HttpUtils();utils.send(HttpMethod.GET, mUrl, new RequestCallBack<String>() {@Overridepublic void onSuccess(ResponseInfo<String> responseInfo) {String result = (String) responseInfo.result;System.out.println("页签详情页返回结果:" + result);parseData(result, false);lvList.onRefreshComplete(true);// 设置缓存CacheUtils.setCache(mUrl, result, mActivity);}@Overridepublic void onFailure(HttpException error, String msg) {Toast.makeText(mActivity, msg, Toast.LENGTH_SHORT).show();error.printStackTrace();lvList.onRefreshComplete(false);}});}/*** 加载下一页数据*/private void getMoreDataFromServer() {HttpUtils utils = new HttpUtils();utils.send(HttpMethod.GET, mMoreUrl, new RequestCallBack<String>() {@Overridepublic void onSuccess(ResponseInfo<String> responseInfo) {String result = (String) responseInfo.result;parseData(result, true);lvList.onRefreshComplete(true);}@Overridepublic void onFailure(HttpException error, String msg) {Toast.makeText(mActivity, msg, Toast.LENGTH_SHORT).show();error.printStackTrace();lvList.onRefreshComplete(false);}});}protected void parseData(String result, boolean isMore) {Gson gson = new Gson();mTabDetailData = gson.fromJson(result, TabData.class);System.out.println("页签详情解析:" + mTabDetailData);// 处理下一页链接String more = mTabDetailData.data.more;if (!TextUtils.isEmpty(more)) {mMoreUrl = GlobalContants.SERVER_URL + more;} else {mMoreUrl = null;}if (!isMore) {mTopNewsList = mTabDetailData.data.topnews;mNewsList = mTabDetailData.data.news;if (mTopNewsList != null) {mViewPager.setAdapter(new TopNewsAdapter());mIndicator.setViewPager(mViewPager);mIndicator.setSnap(true);// 支持快照显示mIndicator.setOnPageChangeListener(this);mIndicator.onPageSelected(0);// 让指示器重新定位到第一个点tvTitle.setText(mTopNewsList.get(0).title);}if (mNewsList != null) {mNewsAdapter = new NewsAdapter();lvList.setAdapter(mNewsAdapter);}// 自动轮播条显示if (mHandler == null) {mHandler = new Handler() {public void handleMessage(android.os.Message msg) {int currentItem = mViewPager.getCurrentItem();if (currentItem < mTopNewsList.size() - 1) {currentItem++;} else {currentItem = 0;}mViewPager.setCurrentItem(currentItem);// 切换到下一个页面mHandler.sendEmptyMessageDelayed(0, 3000);// 继续延时3秒发消息,// 形成循环};};mHandler.sendEmptyMessageDelayed(0, 3000);// 延时3秒后发消息}} else {// 如果是加载下一页,需要将数据追加给原来的集合ArrayList<TabNewsData> news = mTabDetailData.data.news;mNewsList.addAll(news);mNewsAdapter.notifyDataSetChanged();}}/*** 头条新闻适配器* * @author Kevin* */class TopNewsAdapter extends PagerAdapter {private BitmapUtils utils;public TopNewsAdapter() {utils = new BitmapUtils(mActivity);utils.configDefaultLoadingImage(R.drawable.topnews_item_default);// 设置默认图片}@Overridepublic int getCount() {return mTabDetailData.data.topnews.size();//修改为mTopNewsList.size();}@Overridepublic boolean isViewFromObject(View arg0, Object arg1) {return arg0 == arg1;}@Overridepublic Object instantiateItem(ViewGroup container, int position) {ImageView image = new ImageView(mActivity);image.setScaleType(ScaleType.FIT_XY);// 基于控件大小填充图片TopNewsData topNewsData = mTopNewsList.get(position);utils.display(image, topNewsData.topimage);// 传递imagView对象和图片地址container.addView(image);image.setOnTouchListener(new TopNewsTouchListener());// 设置触摸监听return image;}@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {container.removeView((View) object);}}/*** 头条新闻的触摸监听* * @author Kevin* */class TopNewsTouchListener implements OnTouchListener {@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:System.out.println("按下");mHandler.removeCallbacksAndMessages(null);// 删除Handler中的所有消息// mHandler.postDelayed(new Runnable() {//// @Override// public void run() {//// }// }, 3000);break;case MotionEvent.ACTION_CANCEL:System.out.println("事件取消");mHandler.sendEmptyMessageDelayed(0, 3000);break;case MotionEvent.ACTION_UP:System.out.println("抬起");mHandler.sendEmptyMessageDelayed(0, 3000);break;default:break;}return true;}}/*** 新闻列表的适配器* * @author Kevin* */class NewsAdapter extends BaseAdapter {private BitmapUtils utils;// private MyBitmapUtils utils;public NewsAdapter() {utils = new BitmapUtils(mActivity);utils.configDefaultLoadingImage(R.drawable.pic_item_list_default);// utils = new MyBitmapUtils();}@Overridepublic int getCount() {return mNewsList.size();}@Overridepublic TabNewsData getItem(int position) {return mNewsList.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder;if (convertView == null) {convertView = View.inflate(mActivity, R.layout.list_news_item,null);holder = new ViewHolder();holder.ivPic = (ImageView) convertView.findViewById(R.id.iv_pic);holder.tvTitle = (TextView) convertView.findViewById(R.id.tv_title);holder.tvDate = (TextView) convertView.findViewById(R.id.tv_date);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}TabNewsData item = getItem(position);holder.tvTitle.setText(item.title);holder.tvDate.setText(item.pubdate);utils.display(holder.ivPic, item.listimage);String ids = PrefUtils.getString(mActivity, "read_ids", "");if (ids.contains(getItem(position).id)) {holder.tvTitle.setTextColor(Color.GRAY);} else {holder.tvTitle.setTextColor(Color.BLACK);}return convertView;}}static class ViewHolder {public TextView tvTitle;public TextView tvDate;public ImageView ivPic;}@Overridepublic void onPageScrollStateChanged(int arg0) {}@Overridepublic void onPageScrolled(int arg0, float arg1, int arg2) {}@Overridepublic void onPageSelected(int arg0) {TopNewsData topNewsData = mTopNewsList.get(arg0);tvTitle.setText(topNewsData.title);}
}

原因:在加载下一页的时候,mTabDetailData.data.topnews.size()会发生变化,即PagerAdapter的getCount()会发生变化;解决办法:在数据发生变化的时候调用PagerAdapter#notifyDataSetChanged()

TopNewsAdapter mTopNewsAdapter;
...
mViewPager.setAdapter(new TopNewsAdapter());
mIndicator.setViewPager(mViewPager);
...
ArrayList<TabNewsData> news = mTabDetailData.data.news;
mNewsList.addAll(news);
mNewsAdapter.notifyDataSetChanged();

The application's PagerAdapter changed the adapter's contents without calling notifyDataSetChanged相关推荐

  1. The application's PagerAdapter changed the adapter's contents without calling PagerAdapter

    在我们的项目中,为了有好的引导界面,采用了类似微信的引导界面.将代码导入到自己的项目中是,出现了E/AndroidRuntime(20215): java.lang.IllegalStateExcep ...

  2. adapter.notify()、notifyAll()、notifyDataSetChanged ()、notifyDataSetInvalidated ()的区别

    adapter.notify().notifyAll().notifyDataSetChanged ().notifyDataSetInvalidated ()的区别 notify()和notifyA ...

  3. 对ViewPager的理解

    文章目录 一.高度设置wrap_content无效? 二.setOffscreenPageLimit(0)不起作用? 三.Viewpager+Fragment组合使用 一.高度设置wrap_conte ...

  4. Android开发中遇到的bug

    1.将Eclipse项目导入到Android studio 中 很多点9图出现问题解决方法 在build.gradle里添加以下两句: aaptOptions.cruncherEnabled = fa ...

  5. Android 轮播图从 0 到 1

    轮播图是 Android 常用功能之一,效果大概是这样的: 之前我封装写了一个,基本达到了要求,是继承了 Fragment(当时脑袋肯定锈掉了),里面 Viewpager add Fragment,这 ...

  6. ViewPager异常,对ViewPager源码分析

    今天遇到以下异常: java.lang.IllegalStateException: The application's PagerAdapter changed the adapter's cont ...

  7. ViewPager+Fragment实现页卡切换

    现在很多的APP都是这种ui设计模式,在实际开发中经常使用,所以以前我也写过类似的,但基本都是拿来主义,现在正好又遇到了,也不是很复杂,所以就试着自己写一个. 首先是Activity的布局代码: &l ...

  8. 竖直的ViewPager,上下滑动的ViewPager,VerticalViewPager ;

    直接看代码吧,重写Viewpager,改变了手势和切换效果:和正常的Viewpager使用一模一样: /*** ChenboCui 竖向的Viewpager*/ public class VViewP ...

  9. 解析ViewPager(二)——ViewPager源码解析

    前言 前一篇博客介绍了ViewPager的简单使用,这篇博客主要从源码的角度来解析ViewPager. ViewPager的一些变量 ViewPager是一组视图,那么它的父类必然是ViewGroup ...

最新文章

  1. linux之shell脚本学习篇一
  2. node.js require()缓存-可能无效?
  3. saltstack配置管理之YAML(二)
  4. Regtech半月观察(9月上)
  5. 动态语言,静态类型,强类型定义语言,弱类型定义语言,
  6. 学生用的笔记本电脑什么样的好_大学生用的学生党笔记本什么牌子好,听听学姐的...
  7. volatile关键字到底做了什么?
  8. zookeeper 3.6.2启动报错:找不到或无法加载主类 org.apache.zookeeper.server.quorum.QuorumPeerMain
  9. Spark _24 _读取JDBC中的数据创建DataFrame/DataSet(MySql为例)(三)
  10. sql 查询结果为null替换 为 0
  11. android:给程序加锁
  12. poj Muddy Fields
  13. error c2471: cannot update program database vc90.pdb-小楼一夜听春雨-博客园
  14. Java题 细胞分裂
  15. 我学炒外汇 第二十二篇实战心得
  16. vue activated,deactivated生命周期的使用
  17. 显示远程计算机或设备将不接受连接的解决办法
  18. linux下创建CA以及颁发证书
  19. cadence SPB17.4 - allegro - 手工放置过孔
  20. opencv之图像矩 image moments

热门文章

  1. TikTok广告投放指南(基础入门)
  2. 多协议标签交换的MPLS原理
  3. CentOS系统设置开机自启动
  4. Host XXX is not allowed to connect to this MySql 远程连接
  5. Redis在Linux上编译
  6. 开发常用工具(提高开发效率)
  7. Py中re.sub学习【转载】
  8. 8. String to Integer (atoi)
  9. C#3.0 为我们带来什么(5) —— 匿名类型
  10. leetcode 82. 删除排序链表中的重复元素 II