返回介绍

6.4 列表相关的异常

发布于 2024-08-17 23:46:12 字数 3059 浏览 0 评论 0 收藏 0

有Adapter在的地方,就有ListView,就有因此而产生的异常。这些异常基本是因为下拉列表刷新数据时处理不当导致的。这主要是Android本身没有提供标准的下拉刷新数据的列表控件,而网上千奇百怪的下拉刷新控件又都有这样那样的缺陷。封装得再完善的下拉列表控件,也只能确保在大部分机型上工作良好。

6.4.1 Adapter数据源变化但是没通知ListView

异常中的关键字:

The content of the adapter has changed but ListView did not receive a notification.Make sure the content of your adapter is not modified from a background thread,but only from the UI thread.

发生频率:★★★★★

上述异常信息的大体意思是,adapter的内容变化了,但是相应的ListView并不知情。请保证adapter的数据在主线程中进行更改!

首先,一种极端的解决方案是,每次设置adapter中的集合数据时,都要将其clone一份,而不是直接传递一个集合过来。但是这样会比较消耗性能。

其次,要确保每次在Activity中设置adapter的值,而不是在后台线程,有以下几个办法:

1)调用Activity的runOnUiThread()方法,如下所示:

private class OnClickListenerImpl 
  implements View.OnClickListener {
  @Override
  public void onClick(View arg0){
    new Thread(){
      public void run(){
        MainActivity.this.runOnUiThread(new Runnable() {
          @Override
          public void run() {
             textView1.setText("Hello World!");
          }
        });
      }
    }.start();
  }
}

2)调用Handler,通知主线程修改adapter。

3)使用AsyncTask也是一个不错的选择,虽然它也有很多缺陷。

最后,无论何时何地,只要修改了adapter中集合数据的值(比如设置一个集合数据、加一笔数据、清空集合数据),就要马上调用notifyDataSetChanged方法,以确保列表同步更新。

这个异常在Android技术圈儿里可算是大名鼎鼎了,基本上所有的App应用都存在这样的崩溃。

6.4.2 ListView滚动时点击刷新按钮后崩溃

异常中的关键字:

java.lang.IndexOutOfBoundsException:Invalid index 30,size is 1 at

java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251)at

java.util.ArrayList.get(ArrayList.java:304)at android.widget.HeaderViewListAdapter.getView(HeaderViewListAdapter.java:225)

发生频率:★★★

Listview滚动的时候,表示它已经获取了adapter的getCounts(),可能是30,也可能更大。回调用getView(),这个时候将数据clear掉了。当然会报IndexOutOfBoundsException:Invalid index 30,size is 1。这个1是那个header,因为我们使用的是HeaderViewList Adapter。

这种Crash的解决方案是,Listview滚动的时候,将刷新按钮设置为不可点击,如下所示:

public void refresh() {
  startLocation();
  pageNo = 0;
  hasMore = true;
  dataList.clear();
  moreBtn.setVisibility(View.GONE);
  loadFirstPageData();
}

6.4.3 AbsListView的obtainView返回空指针

异常中的关键字:

java.lang.NullPointerException at android.widget.AbsListView.obtain View(AbsListView.java:1521)at android.widget.ListView.makeAndAddView

发生频率:★★★

导致空指针的罪魁祸首是AbsListView的obtainView方法获取不到View,究其原因是getView方法在某些时候返回null。

解决方案很简单,getView的第二个参数convertView是不会为null的,在getView返回值的时候,判断一下是否为null,如果为null,则返回convertView。

6.4.4 Adapter数据源变化但是没调用notifyDataSetChanged

异常中的关键字:

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

发生频率:★★

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文