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()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。

4

1 回答 1

0

不要在布局中添加和删除微调器,而是尝试将其包含在基本itemsLayout文件中并切换可见性。所以,像findViewById(R.id.loading).setVisibility(View.VISIBLE);. 这应该比膨胀一个全新的布局花费更少的时间,这就是你现在正在做的事情。

于 2012-11-26T01:56:10.383 回答