いくつかのデータをレイアウトにロードしようとしています。を介してデータをロードしています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 に設定しています。