2011-12-23 2 views
1

私はエミュレータで動作するアプリケーションを持っていますが、実際のデバイスでテストすると断続的にクラッシュします。私は、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ミリ秒未満で完了していました。多分これは修正であり、そうでないかもしれない。

+0

コードをもっと見る必要があります。とにかく私はあなたがrefactor onPostExecuteをすべきだと思う、今はちょっと混乱しているし、あまりにも多くの作業をする、それはUIを更新するために使用するためのものであり、すべての難しい作業はdoInBackgroundメソッドで行われなければならない – gwa

+0

すべての難しい作業はバックグラウンドで行われています。ホールドアレイは70メガバイトのデータベースからロードされ、数百の計算が実行されています。バックグラウンドタスクは、完了するまでに最大5秒かかることがあります。 (データベースはsdcardにダウンロードされています...)バックグラウンド処理で問題は発生しません。 –

+0

私は以前の答えで嫌なことをしようとしていませんでした。表示されているコードは、1)ListViewに12個のエントリを転送し、y(nnnエントリ)ヘッダーのPage xを更新し、変更されたデータを通知し、進捗ダイアログをオフにします。より多くのコードは、バックグラウンドデータベースの取得と結果の計算を表示するだけです。 –

答えて

0

私は答えとして投稿を閉じるために自分自身に答えるでしょう。

関連する問題