3

いくつかのデータをレイアウトにロードしようとしています。を介してデータをロードしていますAsyncTask。これは、SQLite データソースからデータをロードし、完了時にそのデータをレイアウトに挿入します。この間、タスクの開始時にプログレス バーをレイアウトに追加し、タスクの完了時にレイアウトから削除して、プログレス バーを表示したいと思います。

大まかな概要は次のとおりです。

private class ItemLoader extends AsyncTask<Void, Void, List<Item>> {

    private Context context;
    private LayoutInflater inflater;
    private View loading;

    public DataLoader(Context context) {
        this.context = context;
        this.inflater = LayoutInflater.from(context);
        this.loading = createLoading();
    }

    private View createLoading() {
        return inflater.inflate(R.layout.loading, null);
    }

    @Override
    public void onPreExecute() {
        // Insert 'loading' view into the 'items' layout.
        LinearLayout layout = (LinearLayout) findViewById(R.id.items);
        layout.addView(loading);
    }

    @Override
    protected List<Item> doInBackground(Void... params) {
        return loadItemsFromDataSource();
    }

    private List<Item> loadItemsFromDataSource() {
        ItemsSource d = new ItemsDataSource(context);
        d.open();
        try {
            return d.lookupItems();
        } finally {
            d.close();
        }       
    }

    @Override
    public void onPostExecute(List<Item> items) {
        LinearLayout layout = (LinearLayout) findViewById(R.id.items);
        // Remove 'loading' view from the 'items' layout.
        layout.removeView(loading);
        // Add items to the 'items' layout.
        for (Item item: items) {
            addItemToLayout(item, layout);
        }
    }

私のローディング レイアウトは、 ProgressBar の Android API ドキュメントからコピーされます。

<?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="horizontal" >

    <ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        style="@android:style/Widget.ProgressBar.Small"
        android:layout_marginRight="5dp" />
   <TextView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="@string/loading" />

</LinearLayout>

AsyncTask、アクティビティのonCreate()メソッド中に呼び出されます。

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.itemsLayout);
    ...
    new ItemLoader(this).execute();
}

データがバックグラウンドで読み込まれている間に「読み込み中」スピナーとテキストがレイアウトに追加され、データがレイアウトに追加されるとこのスピナー/テキストが削除されることがわかります。

doInBackground()ただし、メソッドの実行中にスピナーは回転していません。UI スレッド (onPreExecute()およびonPostExecute()メソッド内) でプログレス バーを追加および削除しています。

興味深いことに、データ ソースからデータが読み込まれる前にadd asleep()呼び出しを行うと、スピナーが回転していることがわかります。doInBackground()ただし、データ ソースの呼び出しが行われると、スピナーは回転を停止します。

@Override
protected void doInBackground(Void... params) {
    sleepForFiveSeconds(); // spinner is spinning
    List<Item> items = loadItemsFromDataSource(); // spinner stops spinning
    sleepForFiveSeconds(); // spinner still not spinning
    return items;
}

内で操作される単なるスピナーではありませんAsyncTask。アクティビティのレイアウトで定義するか、アクティビティのonCreate()メソッドで動的に追加することにより、ProgressBar がアクティビティに追加されたときと同じ動作に気付きました。このような場合、スピナーはデータ ソース ルックアップが実行されるまで回転します。データ ソース ルックアップが返されると、再び回転を開始します。

そのため、UI スレッド内でスピナーにアクセスしているように見えますが、バックグラウンド スレッドでのデータ ソース操作により、これらのスピナーが停止しています。

助言がありますか?

追加するために編集: これは私の Nexus 7 (Android 4.2) と HTC 電話 (Android 2.3.4) で、Android マニフェストが最小 SDK バージョンを 10 に設定しています。

4

1 に答える 1

0

スピナーをレイアウトに追加したりレイアウトから削除したりする代わりに、スピナーをベースitemsLayoutファイルに含めて、表示を切り替えてみてください。だから、のようなものfindViewById(R.id.loading).setVisibility(View.VISIBLE);。これは、あなたが今していることである全く新しいレイアウトを膨らませるよりも短い時間で済むはずです。

于 2012-11-26T01:56:10.383 に答える