16

使用 AsyncTaskLoader 时,您将如何更新显示状态的进度条,因为它正在更新?通常你会等待回调在完成后移除,但是如何运行更新呢?你会让主线程(ui)在设置数据时轮询数据吗?

编辑:我说的是AsyncTaskLoader,看看加载器部分。这是类的链接:http: //developer.android.com/reference/android/content/AsyncTaskLoader.html

我想使用它,因为它是未来 :),我知道如何使用 AsyncTask 来做到这一点。

4

6 回答 6

4

您可以使用处理程序,我认为系统比意图更轻

public class MyFragmentActivity extends FragmentActivity{
private final static int MSGCODE_PROGRESS = 1;
private final static int MSGCODE_SIZE = 2;

    private final Handler mHandler = new Handler() {
    public void handleMessage(Message msg) {
        Bundle bundle = msg.getData();
        if(null != bundle){
            int data = msg.getData().getInt(BUNDLE_PROGRESS);
            if(msg.what == MSGCODE_SIZE){
                mProgressBar.setMax(data);
            } else if(msg.what == MSGCODE_PROGRESS){
                mProgressBar.setProgress(data);
            }
        }
    }
};
}

将 mHandler 设置为 AsyncTaskLoader 的构造函数,并从 loadInBackground 更新进度

Bundle bundle = new Bundle();
bundle.putInt(BUNDLE_PROGRESS, lenghtOfFile);
Message msg = new Message();
msg.setData(bundle);
msg.what = MSGCODE_SIZE;
mHandler.sendMessage(msg);
于 2012-04-14T16:18:43.777 回答
4

我将它与我AsyncTaskLoader的 ,一起使用loadInBackground

runOnUiThread(new Runnable() {
    public void run() {
        //UI code
    }
});

但是,这不适用于配置更改(如方向更改)。AsyncTaskLoader如果您需要更新 UI,我不相信最好使用它,但在处理配置更改时效果最好。我不知道为什么他们用自己的权衡来创建 anAsyncTaskLoader和 an 。AsyncTask只会让开发人员感到沮丧和困惑。最重要的是,AsyncTaskLoader文档很少。

于 2012-04-17T02:37:32.747 回答
4

您可以使用加载器来执行此操作,但您需要在 Activity 上保留和更新 WeakReference:

public class LoaderTestActivity extends FragmentActivity implements LoaderCallbacks<Void> {
    private static final int MAX_COUNT = 100;

    private ProgressBar progressBar;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_async_task_test);

        progressBar = (ProgressBar) findViewById(R.id.progressBar1);
        progressBar.setMax(MAX_COUNT);
        AsyncTaskCounter.mActivity = new WeakReference<LoaderTestActivity>(this);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_async_task_test, menu);
        return true;
    }

    public void onStartButtonClick(View v) {
        startWork();
    }

    void startWork() {
        getSupportLoaderManager().initLoader(0, (Bundle) null, this);
    }

    static class AsyncTaskCounter extends AsyncTaskLoader<Void> {
        static WeakReference<LoaderTestActivity> mActivity;

        AsyncTaskCounter(LoaderTestActivity activity) {
            super(activity);
            mActivity = new WeakReference<LoaderTestActivity>(activity);
        }

        private static final int SLEEP_TIME = 200;

        @Override
        public Void loadInBackground() {
            for (int i = 0; i < MAX_COUNT; i++) {
                try {
                    Thread.sleep(SLEEP_TIME);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Log.d(getClass().getSimpleName(), "Progress value is " + i);
                Log.d(getClass().getSimpleName(), "getActivity is " + getContext());
                Log.d(getClass().getSimpleName(), "this is " + this);

                final int progress = i;
                if (mActivity.get() != null) {
                    mActivity.get().runOnUiThread(new Runnable() {

                        @Override
                        public void run() {
                            mActivity.get().progressBar.setProgress(progress);
                        }
                    });
                }
            }
            return null;
        }

    }

    @Override
    public Loader<Void> onCreateLoader(int id, Bundle args) {
        AsyncTaskLoader<Void> asyncTaskLoader = new AsyncTaskCounter(this);
        asyncTaskLoader.forceLoad();
        return asyncTaskLoader;
    }

    @Override
    public void onLoadFinished(Loader<Void> arg0, Void arg1) {

    }

    @Override
    public void onLoaderReset(Loader<Void> arg0) {

    }

}
于 2012-09-20T22:53:19.447 回答
3

我向 Activity 广播了一个 Intent(它由 BroadcastReceiver 接收)。我对这个解决方案不太满意,但它确实有效。AsynTask publishProgress 真的更容易使用。您找到其他解决方案了吗?

于 2012-03-27T14:54:15.693 回答
1

我刚遇到这个问题。我在我的活动中使用了一个静态AtomicInteger来存储进度。加载器通过回调更新它,活动轮询它并显示进度。

在加载程序回调中onLoadFinished,我隐藏了我的进度面板,这会导致轮询循环退出。

通常我会避免静态状态,但我认为总的来说这比替代方案更简单。就我而言,我在横向上有不同的布局,所以我更乐意让方向变化表现正常。

private Handler progressHandler; // init with new Handler(getMainLooper())
private static AtomicInteger progress = new AtomicInteger(0);

...

private void beginProgressUiUpdates() {
    progress.set(0);
    displayProgress();
    progressHandler.postDelayed(pollProgress, PROGRESS_POLL_PERIOD_MILLIS);
}

private Runnable pollProgress = new Runnable() {
    public void run() {
        if (findViewById(R.id.progressPanel).getVisibility() == View.VISIBLE) {
            displayProgress();
            progressHandler.postDelayed(pollProgress, PROGRESS_POLL_PERIOD_MILLIS);
        }
    }
};

private void displayProgress() {
    ((ProgressBar)findViewById(R.id.progressBar)).setProgress(progress.get());
}
于 2015-02-07T14:11:56.007 回答
0

离开@garmax 的回答,我找到了一个网站,展示了如何将AsyncTaskLoaders 与 Fragments 结合起来:http://habrahabr.ru/post/131560/

它是俄语的,但我可能会稍后发布我的实现。

编辑:这是包含该实现的 ZIP 的链接:http ://www.2shared.com/file/VW68yhZ1/SampleTaskProgressDialogFragme.html

于 2012-04-19T18:44:12.183 回答