我正在尝试将一些数据加载到布局中。我正在通过 加载数据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()
andonPostExecute()
方法中)。
有趣的是,如果在从数据源加载数据之前添加一个sleep()
调用,那么我可以看到微调器正在旋转。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
. 当 ProgressBar 添加到活动时,我注意到相同的行为,要么在活动的布局中定义它,要么在活动的onCreate()
方法中动态添加它。在这些情况下,微调器一直在旋转,直到执行数据源查找。一旦数据源查找返回,它将再次开始旋转。
因此,似乎在 UI 线程中访问了微调器,但后台线程中的数据源操作导致这些微调器停止。
有什么建议么?
编辑添加:这是我的 Nexus 7 (Android 4.2) 和 HTC 手机 (Android 2.3.4),android manifest 将最低 SDK 版本设置为 10。