使用AsyncTaskLoader时,如何更新显示正在更新状态的进度条?通常你等待回调完成后删除,但是如何运行更新? 您是否让主线程(ui)在设置数据时轮询数据?
编辑:我说的是 AsyncTaskLoader ,请查看加载器部分。以下是课程的链接:http://developer.android.com/reference/android/content/AsyncTaskLoader.html
我想使用它,因为它的未来:),我知道如何使用AsyncTask。
答案 0 :(得分: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);
答案 1 :(得分:4)
您可以使用加载器执行此操作,但您需要在活动中保留并更新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) {
}
}
答案 2 :(得分:3)
我向活动广播一个意图(并且它由BroadcastReceiver接收)。我对这个解决方案不是很满意,但它确实有效。 AsynTask publishProgress真的更容易使用。你找到了其他解决方案吗?
答案 3 :(得分:3)
我在AsyncTaskLoader
loadInBackground
runOnUiThread(new Runnable() {
public void run() {
//UI code
}
});
但是,这不适用于配置更改(如方向更改)。我不相信如果您需要更新UI,AsyncTaskLoader
最好使用,但在处理配置更改时效果最佳。我不知道为什么他们创造了AsyncTaskLoader
和AsyncTask
各自的权衡。只是让开发人员感到沮丧和困惑。最重要的是AsyncTaskLoader
只有很少的文档。
答案 4 :(得分: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());
}
答案 5 :(得分:0)
关闭@ garmax的答案,我发现了一个网站,展示了如何将AsyncTaskLoader
与片段结合起来:http://habrahabr.ru/post/131560/
这是俄语,但我可能会在稍后发布我的实现。
编辑:以下是包含该实施的ZIP的链接:http://www.2shared.com/file/VW68yhZ1/SampleTaskProgressDialogFragme.html