我正在尝试将一些数据加载到布局中。我通过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);
}
}
我的加载布局是从Android API docs for ProgressBar:
复制的<?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();
}
我可以看到,当数据加载到后台时,'loading'微调器和文本被添加到我的布局中,并且当数据添加到布局时,这个微调器/文本被删除。
但是当doInBackground()
方法运行时,微调器没有旋转。我正在添加和删除UI线程中的进度条(在onPreExecute()
和onPostExecute()
方法中)。
有趣的是,如果在从数据源加载数据之前在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。
答案 0 :(得分:0)
不要在布局中添加和删除微调器,而是尝试将其包含在基础itemsLayout
文件中,然后切换可见性。所以,像findViewById(R.id.loading).setVisibility(View.VISIBLE);
之类的东西。这比使整个新布局膨胀所花费的时间更短,这正是您现在正在做的事情。