私はエミュレータで動作するアプリケーションを持っていますが、実際のデバイスでテストすると断続的にクラッシュします。私は、Code Overtones Android Crashレポートの修正版を実行しています。 (http://jyro.blogspot.com/2009/09/crash-report-for-android-app.html)電子メールの原因の状態:Listview notifydatachanged()timing concern
アダプターの内容は変更されましたが、ListViewは受信しませんでしたa 通知。アダプタの内容がバックグラウンドスレッドの に変更されていないことを確認してください。ただし、UIスレッドからのみ取得してください。 [アダプタ(クラス android.widget.SimpleAdapter)と リストビュー(2131296303、クラスandroid.widget.ListView)に】
コードは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アダプタに関連付けられた配列です。 (この方法でキューイングするとパフォーマンスが向上することが判明しました。データベースアクセス中にアダプタがループしていない可能性があります)
クラッシュは常にホーム後の最初のエントリキーを終了してから、リスト・アクティビティーを呼び出すトップレベル・アクティビティーに戻ります。クラッシュ間の時間は、連続試験中、30分から2時間です。クラッシュしているコードは何百回も横断されており、出口がなく線形です。
コードの見直しで見つかる可能性がある唯一の穴は、配列のロードの前にあるclear()です。クリア関数は1つの変更として機能し、追加のグループは2つ目の変更として機能しますか?タイミングの考慮事項はありますか?リストには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>();
ホールド配列は、アダプターの配列の複製です。ホールド配列は、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>
--------別の更新--------------
opPostExecute関数にいくつかのコードを追加しました。
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時間の安定したテストの後、まだクラッシュしていません。コードの前に、私は少なくとも1回、時には2時間に2回クラッシュするでしょう。私はクリア後にnotifydatasetchangedを追加し、300msecの睡眠を続けた。元の通知が失われたため、オペレーティングシステムが足元を歩いていたと思います。データベースのクエリには最大8秒かかる場合がありますが、ほとんどの場合、即時回答です。進捗状況のダイアログに完全に設定する機会はありませんでした。画面がちらつき、リストビューが表示されます。進行状況の表示は決して特定できませんでした。 (進行状況ダイアログは、preExecute関数でオンになっています。)AsyncTask全体が300ミリ秒未満で完了していました。多分これは修正であり、そうでないかもしれない。
コードをもっと見る必要があります。とにかく私はあなたがrefactor onPostExecuteをすべきだと思う、今はちょっと混乱しているし、あまりにも多くの作業をする、それはUIを更新するために使用するためのものであり、すべての難しい作業はdoInBackgroundメソッドで行われなければならない – gwa
すべての難しい作業はバックグラウンドで行われています。ホールドアレイは70メガバイトのデータベースからロードされ、数百の計算が実行されています。バックグラウンドタスクは、完了するまでに最大5秒かかることがあります。 (データベースはsdcardにダウンロードされています...)バックグラウンド処理で問題は発生しません。 –
私は以前の答えで嫌なことをしようとしていませんでした。表示されているコードは、1)ListViewに12個のエントリを転送し、y(nnnエントリ)ヘッダーのPage xを更新し、変更されたデータを通知し、進捗ダイアログをオフにします。より多くのコードは、バックグラウンドデータベースの取得と結果の計算を表示するだけです。 –