ProgressBar在后台任务中的数据源操作期间不旋转

时间:2012-11-26 01:46:59

标签: android android-asynctask android-progressbar

我正在尝试将一些数据加载到布局中。我通过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。

1 个答案:

答案 0 :(得分:0)

不要在布局中添加和删除微调器,而是尝试将其包含在基础itemsLayout文件中,然后切换可见性。所以,像findViewById(R.id.loading).setVisibility(View.VISIBLE);之类的东西。这比使整个新布局膨胀所花费的时间更短,这正是您现在正在做的事情。