5

200アイテムのリストビューがあります。各行にカスタムビューを使用します。計算に時間がかかるコードがあります。このため、リストはスクロール時にハングし、読み込みが遅くなります(2〜3秒)。

SimpleCursorAdapterをサブクラス化し、FilterableとSectionIndexerを使用しています。

最初にレコードの名前を表示し、計算をスレッドに入れて、後で表示されるようにすることを念頭に置いています。

一部の作業を延期し、後でリストビューを更新して計算データを含めるにはどうすればよいですか?これは、ユーザーの操作なしでオンザフライで表示されるはずです。

4

2 に答える 2

2

androidのAndroidUIはシングルスレッドであるため、長時間の操作を実行するとブロックされます。

通常のJavaスレッドを実行し、情報をフィードバックできるメインUIクラスにHandler()を含めることができます。だが..

最も簡単な方法は、AsyncTask()を作成することです。それらはわずかな変更を加えたJavaスレッドです。メイン計算の前後にUI操作を実行できます。したがって、たとえば:

 private class AndroidThread extends AsyncTask {
      protected Object doInBackground(Object... params) {
           return result;
      }

      protected void onPostExecute(Object result) {
           // do things here with the result of the doInBackground function
           // Like: "UiElement"."performTask(result)"
      }
 }

AsyncTaskの詳細については、こちらを参照してください

于 2010-03-27T09:32:29.690 に答える
1

うーん、興味深い質問です。ここにいくつかの簡単な考えがあります:

1)直接取得できる値、つまりレコードの名前をリストに直接入力します。計算に時間がかかる可能性のあるすべてのものについては、「読み込み中...」などのデフォルト値のままにします。

2)計算を行うための2番目のスレッドを作成しますが、すべてが計算されないようにするには、ListViewのonScrollStateChangedリスナーを使用します。これにより、リストがアイドル状態であるか、タッチスクロールでゆっくりスクロールされている場合にのみ、バックグラウンド作業を実行できます。言い換えると、計算が終了する前に行がかなり過ぎてしまうため、「フリング」モードのときに気にしないでください。

3)ロードステージをスレッドにエンキューする方法が完全にはわかりません。読み込みスレッドを1つだけにしたい場合は、各行に新しいスレッドを開くのはかなり面倒で、電話はマルチコアではないため無意味ですが、それはスレッドにキューイングシステムが必要であることを意味します。つまり、スレッドは計算を待機している行を認識している必要がありますが、それをどのように行うかについてはまだ考えていません。ただし、これはどの行が表示されるかにも関連付けられている必要があります。リストのずっと前の行の情報を計算するスレッドには意味がありません。

4)ロードスレッドが特定の行を終了するときはいつでも、リストアダプタでnotifyDatasetChanged()を呼び出すことができます。ListViewが表示されている行だけでなく、すべての行のデータを更新しようとすると、これは少し重くなる可能性がありますが、確認するには実験が必要です。

これらのアイデアが少し役立つことを願っています!


コメントへの応答:行がいつ表示されるかを尋ねていると仮定すると、ListView.OnScrollListenerを実装することでそれを行うことができます。ApiDemos List13からインスピレーションを得ましたが、関連するコードは次のとおりです。

public class YourClass extends ListActivity implements ListView.OnScrollListener {
    public void onCreate(Bundle sIS){
        (...)
        // Note, you may have to write your own list adapter, extending BaseAdapter
        // See List13 in Api Demos for an example if you're not sure how to do that
        setListAdapter(yourImageAdapter); 
        getListView().setOnScrollListener(this);
    }

    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
            int totalItemCount) {
        Log.d(LOG_TAG, "onScroll, firstVisibleItem = " + firstVisibleItem +
                ", visibleItemCount = " + visibleItemCount
                + ", totalItemCount = " + totalItemCount);
    }

    public void onScrollStateChanged(AbsListView view, int scrollState) {
        Log.d(LOG_TAG, "onScrollStateChanged called, scrollState = " + scrollState);
        switch (scrollState) {
        case OnScrollListener.SCROLL_STATE_IDLE:
            int first = view.getFirstVisiblePosition();
            int count = view.getChildCount();

            Log.d(LOG_TAG, "first = " + first + ", count = " + count);

            break;
        case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
            //Scrolling with the finger touching the screen
            break;

        case OnScrollListener.SCROLL_STATE_FLING:
            // User 'threw' the list up or down and it's scrolling rapidly
            break;
        }
    }
}

これにより、リストのすべてがわかります。スクロールしているのか、表示されているのかなどです。読み込みスレッドで表示されている行のバックグラウンド作業のみを行う場合は、不要なオーバーヘッドを減らすのに役立ちます。

BaseAdapterに関するもう1つのポイント:他の形式のリストアダプタを使用したことはないので、すべて同じである可能性がありますが、BaseAdapterの非常に便利な点の1つは、各行の「インフレーション」を個別に処理できることです。リストに新しい行が表示されるたびに、getViewが呼び出されます。そこにカスタムコードを入れて、情報がまだ計算されていない場合は「読み込み中...」を入力したり、計算されている場合は実際に表示したりできます。

ちなみに、このリストで実際に何を計算しているので、時間がかかりますか?

于 2010-03-26T23:56:12.903 に答える