从 AsyncTaskLoader 更新进度条?

发布于 2024-12-31 23:07:21 字数 393 浏览 3 评论 0原文

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

编辑:我正在谈论 AsyncTaskLoader,看看加载程序部分。这是类的链接: http://developer.android.com/reference/android /content/AsyncTaskLoader.html

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

When using a AsyncTaskLoader how would you update a progressbar showing the status as it is being updated? Normally you wait for the callback to remove when done, but how to do running updates?
Would you let the main thread (ui) poll the data as it is being set or something?

Edit: I'm talking about AsyncTaskLoader, look at the loader part. Here is link to class: http://developer.android.com/reference/android/content/AsyncTaskLoader.html

I want to use it because its the future :), I know how to do this with AsyncTask.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

秋凉 2025-01-07 23:07:22

您可以使用加载器来做到这一点,但您需要保留并更新 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) {

    }

}

You can do that with loaders, but you need to keep and update a WeakReference on your Activity :

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) {

    }

}
口干舌燥 2025-01-07 23:07:22

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

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);

You can use handler, i think it will be lighter for system than intent

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);
            }
        }
    }
};
}

Set mHandler to constructor of AsyncTaskLoader and from loadInBackground you can update progress

Bundle bundle = new Bundle();
bundle.putInt(BUNDLE_PROGRESS, lenghtOfFile);
Message msg = new Message();
msg.setData(bundle);
msg.what = MSGCODE_SIZE;
mHandler.sendMessage(msg);
擦肩而过的背影 2025-01-07 23:07:22

我将其与我的 AsyncTaskLoader 一起使用,位于 loadInBackground 内部。

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

但是,这不适用于配置更改(例如方向更改)。如果您需要更新 UI,我不相信 AsyncTaskLoader 是最好的选择,但它在处理配置更改时效果最好。我不知道为什么他们创建了一个 AsyncTaskLoader 和一个 AsyncTask ,每个都有自己的权衡。只会让开发人员感到沮丧和困惑。除此之外,AsyncTaskLoader 的文档很少。

I'm using this with my AsyncTaskLoader, inside of loadInBackground

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

However, this doesn't work with an configuration change (like orientation change). I'm not convinced AsyncTaskLoader is the best to use if you need to update the UI, but it works best when handling configuration changes. I don't know why they created both an AsyncTaskLoader and an AsyncTask each with their own tradeoffs. Just frustrates and confuses developers. On top of that AsyncTaskLoader has very little documentation.

淡淡绿茶香 2025-01-07 23:07:22

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

I broadcast an Intent to the Activity (and it's received by a BroadcastReceiver). I'm not very happy with this solution but it works. The AsynTask publishProgress is really easier to use. Did you find some other solution ?

烟若柳尘 2025-01-07 23:07:22

我刚刚遇到这个问题。我使用了静态 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());
}

I just had this problem. I used a static AtomicInteger in my activity to store the progress. The loader updates it via a callback and the activity polls it and displays the progress.

In the loader callback onLoadFinished I hide my progress panel, which causes the polling loop to exit.

Usually I'd avoid static state, but I think overall this is simpler than the alternatives. In my case, I have a different layout in landscape, so I'm happier leaving the orientation changes behaving as normal.

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());
}
最美不过初阳 2025-01-07 23:07:22

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

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

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

Going off @garmax's answer, I found a site that showed how to combine AsyncTaskLoaders with Fragments on: http://habrahabr.ru/post/131560/

It's in Russian, but I might post my implementation of it later.

EDIT: Here's a link to the ZIP containing that implementation: http://www.2shared.com/file/VW68yhZ1/SampleTaskProgressDialogFragme.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文