Listview notifydatachanged()时间问题

时间:2011-12-23 17:45:58

标签: android android-listview

我有一个适用于模拟器的应用程序,但在真实设备上进行测试时会间歇性地崩溃。我正在运行Code Overtones Android Crash报告的修改版本。 (http://jyro.blogspot.com/2009/09/crash-report-for-android-app.html)电子邮件原因说明:

  

适配器的内容已更改,但ListView未收到   通知。确保未修改适配器的内容   来自后台线程,但仅来自UI线程。 [在   ListView(2131296303,类android.widget.ListView)与Adapter(类   android.widget.SimpleAdapter)]

代码不会修改UI主线程之外的适配器。对适配器的所有访问都是通过AsyncTask的onPostExecute进行的。代码是:

    @Override
    protected void onPostExecute(String result) {
        MyLog.d(TAG, "onPostExecute");
        foodDescArrayList.clear();
        int entries = holdFoodDescArrayList.size();
        HashMap<String, String> listEntry;
        for (int i = 0; i < entries; i++) {
            listEntry = new HashMap<String, String>();
            listEntry = holdFoodDescArrayList.get(i);
            foodDescArrayList.add(listEntry);
        }
        holdFoodDescArrayList.clear();
        hideProgress();
        foodDescAdapter.notifyDataSetChanged();
        String ents = " entries";
        if (rowsReturned == 1) {
            ents = " entry";
        }
        foodDescHeader.setText("Page " + Integer.toString(currentPage + 1)
                + " of " + Integer.toString(pageCount) + " (" + Integer.toString(rowsReturned) + ents + ")");
        loadActive = false;
    }

holdFoodDescArrayList是一个独立的列表,填充在SQLite数据库的后台任务中。 foodDescArrayList是与ListView适配器关联的数组。 (我发现在以这种方式排队时会有性能提升。也许是因为在数据库访问期间适配器不在循环中。开销较少?)

崩溃始终发生在主键退出后的第一个条目(onCreate)上,然后重新进入调用列表活动的顶级活动。在连续测试期间,崩溃之间的时间为30分钟至2小时。崩溃的代码已经遍历了数百次并且是线性的,没有退出。

我在查看代码时可以找到的唯一可能的漏洞是数组加载前的clear()。明确的功能是作为一个变化而作为第二个变化添加的吗?有时间考虑吗?列表中有1到24个条目,因此加载应该花费毫秒而不是秒......

我正在寻找想法和线索。请扫描代码,看看代码中是否有明显的错误或副作用。它是应用程序中唯一更改ListView关联数组数据的位置。后台代码仅改变保持数组。

请不要在答案中输入完整的代码重写。我正在继续尝试找到原因和原因。我不想浪费你几分钟的时间。我会在接下来的几天里经常看这篇文章并回答我发现的任何问题。谢谢你的帮助...

-----------更新以添加请求的代码----------

onCreate中的代码是:

    setContentView(R.layout.fooddeslist);
    foodDescHeader = (TextView) findViewById(R.id.foodDescHeading);
    foodDescListView = (ListView) findViewById(R.id.foodDescList);
    foodDescArrayList = new ArrayList<HashMap<String, String>>();
    holdFoodDescArrayList = new ArrayList<HashMap<String, String>>();
    foodDescAdapter = new SimpleAdapter(this, foodDescArrayList,
            R.layout.longdescitem, new String[] { GC.FOODDESCLIST_LINE1,
                    GC.FOODDESCLIST_LINE2 },
            new int[] { R.id.longdescListItemLine1,
                    R.id.longdescListItemLine2 });
    foodDescListView.setAdapter(foodDescAdapter);
    registerForContextMenu(foodDescListView);

数组条目是:

    listEntry = new HashMap<String, String>();

hold数组是适配器数组的副本。 hold数组加载到AsyncTask中的doInBackground函数中。我会显示背景代码,但它大约有500行代码。最终结果是保持数组加载了2行显示和每个条目唯一的辅助数据。选择条目时使用的其他表中各种数据位的行ID。重复的表允许我加载数组(到千兆赫处理器)加载数组。 UI运行后执行传输只需几毫秒。

longdescitem.xml是:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical">

     <TextView android:id="@+id/longdescListItemLine1"
        android:textStyle="italic"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="#ff9900"
        />
     <TextView android:id="@+id/longdescListItemLine2"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:textColor="#b89300"

         />
</LinearLayout>

R.layout.fooddesclist是:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/foodDescHeading"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginLeft="2dip"
        android:text="Page 1 of 10 (nnn entries)"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:textColor="#b89300" />

    <ImageButton
        android:id="@+id/foodDescForward"
        android:layout_width="50px"
        android:layout_height="50px"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_marginRight="12dip"
        android:layout_marginTop="5dip"
        android:background="@drawable/forward"
        android:clickable="true"
        android:onClick="foodDescForwardClicked" />

    <ImageButton
        android:id="@+id/foodDescBack"
        android:layout_width="50px"
        android:layout_height="50px"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="12dip"
        android:layout_marginTop="5dip"
        android:background="@drawable/back"
        android:clickable="true"
        android:onClick="foodDescBackClicked" />

    <View
        android:id="@+id/foodDescSpacer1"
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:layout_alignParentLeft="true"
        android:layout_below="@id/foodDescForward"
        android:layout_marginBottom="2dip"
        android:layout_marginTop="2dip"
        android:background="@drawable/divider" />

    <ListView
        android:id="@+id/foodDescList"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@id/foodDescSpacer1"
        android:layout_marginLeft="2dip"
        android:layout_marginRight="2dip"
        android:cacheColorHint="#00000000"
        android:divider="#b89300"
        android:dividerHeight="1.0px" />

</RelativeLayout>

--------另一次更新--------------

我在opP​​ostExecute函数中添加了一些代码。

    protected void onPostExecute(String result) {
        MyLog.d(TAG, "onPostExecute");
        foodDescArrayList.clear();
        foodDescAdapter.notifyDataSetChanged();
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            MyLog.d(TAG, "Sleep failed: " + e.getMessage());
        }
        int entries = holdFoodDescArrayList.size();
        HashMap<String, String> listEntry;
        for (int i = 0; i < entries; i++) {
            listEntry = new HashMap<String, String>();
            listEntry = holdFoodDescArrayList.get(i);
            foodDescArrayList.add(listEntry);
        }
        holdFoodDescArrayList.clear();
        hideProgress();
        foodDescAdapter.notifyDataSetChanged();
        String ents = " entries";
        if (rowsReturned == 1) {
            ents = " entry";
        }
        foodDescHeader.setText("Page " + Integer.toString(currentPage + 1)
                + " of " + Integer.toString(pageCount) + " (" + Integer.toString(rowsReturned) + ents + ")");
        loadActive = false;
    }

在Atrix上进行了两个小时的稳定测试之后,它还没有崩溃。在代码之前,我会在2小时内至少崩溃一次,有时两次。我在清除后添加了notifydatasetchanged,然后以300毫秒的睡眠进行跟踪。我认为操作系统正在踩踏脚趾,因为原始通知丢失了。虽然数据库查询最多可能需要8秒,但大部分时间都是即时回答。进度对话框从未有机会完全设置。屏幕会闪烁,然后列表视图会显示。进度显示无法识别。 (在preExecute函数中打开进度对话框。)整个AsyncTask在不到300毫秒的时间内完成。也许这是一个修复,也许不是。

1 个答案:

答案 0 :(得分:0)

我自己回答这个问题,以回答这个问题。