16

AsyncTaskLoaderを使用する場合、更新中のステータスを示すプログレスバーをどのように更新しますか?通常、完了したらコールバックが削除されるのを待ちますが、更新を実行するにはどうすればよいですか?メインスレッド(ui)に、設定中のデータなどをポーリングさせますか?

編集:私はAsyncTaskLoaderについて話している、ローダーの部分を見てください。クラスへのリンクは次のとおりです:http://developer.android.com/reference/android/content/AsyncTaskLoader.html

将来的に使用したいのですが:)、AsyncTaskでこれを行う方法を知っています。

4

6 に答える 6

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

    }

}
于 2012-09-20T22:53:19.447 に答える
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
    }
});

ただし、これは構成の変更 (向きの変更など) では機能しません。AsyncTaskLoaderUI を更新する必要がある場合に使用するのが最適であるとは確信していませんが、構成の変更を処理する場合に最適です。なぜ彼らが独自のトレードオフでAsyncTaskLoaderan とeachの両方を作成したのかはわかりません。AsyncTask開発者を苛立たせ、混乱させるだけです。その上、AsyncTaskLoaderドキュメントはほとんどありません。

于 2012-04-17T02:37:32.747 に答える
3

インテントをアクティビティにブロードキャストします(BroadcastReceiverによって受信されます)。私はこの解決策にあまり満足していませんが、それは機能します。AsynTaskpublishProgressは本当に使いやすいです。他の解決策を見つけましたか?

于 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 に答える