The application's PagerAdapter changed the adapter's contents without calling notifyDataSetChanged
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(); 《新程序员》:云原生和全面数字化实践50位技术专家共同创作,文字、视频、音频交互阅读总结
以上是生活随笔为你收集整理的The application's PagerAdapter changed the adapter's contents without calling notifyDataSetChanged的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: Android下的Linux
- 下一篇: java.lang.NoSuchMeth