Update progressbar from AsyncTaskLoader?

前端 未结 6 1685
粉色の甜心
粉色の甜心 2021-01-31 05:30

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

相关标签:
6条回答
  • 2021-01-31 06:14

    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

    0 讨论(0)
  • 2021-01-31 06:15

    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);
    
    0 讨论(0)
  • 2021-01-31 06:15

    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());
    }
    
    0 讨论(0)
  • 2021-01-31 06:24

    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) {
    
        }
    
    }
    
    0 讨论(0)
  • 2021-01-31 06:24

    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.

    0 讨论(0)
  • 2021-01-31 06:25

    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 ?

    0 讨论(0)
提交回复
热议问题