现在的位置: 首页 > 综合 > 正文

各位看过来–ViewPager在4.0下存在的兼容性问题

2013年10月13日 ⁄ 综合 ⁄ 共 2556字 ⁄ 字号 评论关闭

  通过查看统计平台反馈回来的错误报告,发现在android 4.0系统下,Viewpager屡屡报错。原因与Viewpager中包含有自定义Listview有关,而原生的Listview控件不会报错。Viewpager中存放着四个自定义的Listview(下拉刷新),在切换的过程中就会崩溃,如图:

 

 出错位置在PagerAdapter的destroyItem方法中,会报java.lang.IllegalArgumentException: The observer is null
错误,堆栈信息如下,请仔细看:

java.lang.IllegalArgumentException: The observer is null.
at android.database.Observable.unregisterObserver(Observable.java:59)
at android.widget.BaseAdapter.unregisterDataSetObserver(BaseAdapter.java:42)
at android.widget.HeaderViewListAdapter.unregisterDataSetObserver(HeaderViewListAdapter.java:256)
at android.widget.AbsListView.onDetachedFromWindow(AbsListView.java:2309)
at android.view.View.dispatchDetachedFromWindow(View.java:8197)
at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1968)
at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1966)
at android.view.ViewGroup.removeViewInternal(ViewGroup.java:3257)
at android.view.ViewGroup.removeViewInternal(ViewGroup.java:3237)
at android.view.ViewGroup.removeView(ViewGroup.java:3185)
at com.aheudev.a.slickdeals.adapters.DealPageAdapter.destroyItem(DealPageAdapter.java:174)
at android.support.v4.view.ViewPager.populate(ViewPager.java:415)
at android.support.v4.view.ViewPager.completeScroll(ViewPager.java:696)
at android.support.v4.view.ViewPager.computeScroll(ViewPager.java:668)
………………………………
………………………………
 

  

而这些错误来源于我们复写的PagerAdapter中的这个方法:

@Override
public void destroyItem(View collection, int position, Object view) {
    ((ViewPager) collection).removeView((View) view);
}

 

首先我们来说一下解决方法:

 原因是Listview的adapter 中的unregisterDataSetObserver方法被调用了两次,导致observer为空。我们只要复写与Listview绑定的适配器中的unregisterDataSetObserver方法即可,在其中做一个非空判断即可。按如下代码:

 

@Overridepublic void unregisterDataSetObserver(DataSetObserver observer) {  
  if (observer != null) {     
   super.unregisterDataSetObserver(observer); 
   }
}

错误分析:

   
  仔细观察堆栈信息红色部分发现,错误的源头来源于BaseAdapter.unregisterDataSetObserver方法。
  经过Log 大概了解到,在滑动过程中viewpager会移除不在视野范围内的View。
 

  如上图,比如移动到第三个tab页,会把第一个tab页中的view移除;移动到第四个tab页会把第二个tab页中的view移除掉。当我们再次移动到第三个tab页时,Viewpager依旧会将第一个tab页中的View移除……


 
有移除就有添加,本来这没有什么。但是通过Log打印的信息,我发现在android 4.0中,Viewpager除了移除View中的列表组件Listview之外,还同时多做了一件事情,那就是调用列表组件Listview的适配器Adapter的unregisterDataSetObserver方法,移除了与适配器绑定数据集观察者DataSetObserver ,也就是那个observer。但是在4.0以下的系统中,ViewPager没有移除列表组件Listview的数据集观察者observer。


  所以当再次移动到第三个tab时,会继续卸载位于第一个位置tab中的listview的观察者 ,这时因为观察者已经被卸载为空,而报非法的参数错误。


  让人疑惑的就是4.0下:原生的Listview在移除观察者时,没有任何问题。自定义的Listview在移除观察者时,就会报以上的堆栈信息。如果有哪位大虾知道出现这种不兼容原因,欢迎指教。

   参考资料:http://stackoverflow.com/questions/7290841/java-lang-illegalargumentexception-the-observer-is-null


  原文链接:http://www.67tgb.com/?p=495    

 欢迎访问:望月听涛

 

【上篇】
【下篇】

抱歉!评论已关闭.