Android Loader vs AsyncTask on button click

I have an activity that does not require data from the server on boot - just a simple init for the ui

The user interface has several buttons.

The user clicks on one of them, and the application sends a request to the server (call rest) While the request is being processed, the counter shows (about 10 seconds)

It currently uses AsyncTask - so if the app changes portrait to album - the activity restarts and I lose the process

The second option is to use a Loader - the problem is that it starts when the button is pressed - not when the activity starts

This leads to many exceptions - when the LoaderManager dispatches events to an unloaded element

Is there any solution?

a few comments: - 10 seconds for example - blocking the user to one orientation is not an option - the service is overkill for a simple rest call

+1


source to share


4 answers


public class TestActivity extends FragmentActivity {

    private Button one;
    private Button two;

    private final int ONE_ID = 0;
    private final int TWO_ID = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        one = (Button) findViewById(R.id.one);
        two = (Button) findViewById(R.id.two);

        one.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getLoaderManager().restartLoader(ONE_ID, null, callbacks);
            }
        });

        two.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getLoaderManager().restartLoader(ONE_ID, null, callbacks);
            }
        });

        Loader<AsyncTaskLoaderResult<Result>> loader = getLoaderManager().getLoader(ONE_ID);
        if (loader != null) {
            getLoaderManager().initLoader(ONE_ID, null, callbacks);
        }
        loader = getLoaderManager().getLoader(TWO_ID);
        if (loader != null) {
            getLoaderManager().initLoader(TWO_ID, null, callbacks);
        }


    }

    public static class AsyncTaskLoaderResult<E> {
        public E data;
        public Bundle args;
    }

    public static class Result {

    }

    private LoaderManager.LoaderCallbacks<AsyncTaskLoaderResult<Result>> callbacks = new LoaderManager.LoaderCallbacks<AsyncTaskLoaderResult<Result>>() {
        @Override
        public Loader<AsyncTaskLoaderResult<Result>> onCreateLoader(int id, Bundle args) {
            /**
             * according different Id, create different AsyncTaskLoader
             */
            switch (id) {
                case ONE_ID:
                    return new OneAsyncTaskLoader(TestActivity.this);
                case TWO_ID:
                    return new TwoAsyncTaskLoader(TestActivity.this);
            }
            return null;
        }

        @Override
        public void onLoadFinished(Loader<AsyncTaskLoaderResult<Result>> loader, AsyncTaskLoaderResult<Result> data) {
            /**
             * handle result
             */
            switch (loader.getId()) {

            }

            getLoaderManager().destroyLoader(loader.getId());
        }

        @Override
        public void onLoaderReset(Loader<AsyncTaskLoaderResult<Result>> loader) {

        }
    };

    public static class OneAsyncTaskLoader extends AsyncTaskLoader<AsyncTaskLoaderResult<Result>> {

        private AsyncTaskLoaderResult<Result> result;

        public OneAsyncTaskLoader(Context context) {
            super(context);
        }

        @Override
        protected void onStartLoading() {
            super.onStartLoading();
            if (result != null) {
                deliverResult(result);
            } else {
                forceLoad();
            }
        }

        @Override
        public AsyncTaskLoaderResult<Result> loadInBackground() {
            /**
             * send request to server
             */
            result = new AsyncTaskLoaderResult<Result>();
            result.data = null; //  result.data comes from server response
            return result;
        }
    }

    public static class TwoAsyncTaskLoader extends AsyncTaskLoader<AsyncTaskLoaderResult<Result>> {


        private AsyncTaskLoaderResult<Result> result;

        public TwoAsyncTaskLoader(Context context) {
            super(context);
        }

        @Override
        protected void onStartLoading() {
            super.onStartLoading();
            if (result != null) {
                deliverResult(result);
            } else {
                forceLoad();
            }
        }

        @Override
        public AsyncTaskLoaderResult<Result> loadInBackground() {
            /**
             * send request to server
             */
            result = new AsyncTaskLoaderResult<Result>();
            result.data = null; //  result.data comes from server response
            return result;
        }
    }
}

      



+3


source


First, you can fix the orientation change issue by declaring

android:configChanges="orientation"

      

or savedInstanceState ()



But the real problem is that the user looks at the counter for 10 seconds. Most users won't be patient enough for this. I don’t know what your application does, so it’s difficult to give an exact suggestion, but I can say that you need to do your web content in AsyncTask

, but let the user do other things.

You can allow the user to do other things while AsyncTask

completing or putting this code in [Service ( http://developer.android.com/guide/components/services.html ). Anyway, don't force your users to look at screen for 10 seconds of rotation ... they won't be YOUR users for a long time

0


source


If you use AsyncTask

to do this, you can use Service

or use onRetainNonConfigurationInstance instead or Fragment.setRetainInstance

to allow the AsyncTask

configuration changes to live.

Or disable config changes: I've used this in the past with some success.

0


source


Here's a good article on the topic:

http://www.javacodegeeks.com/2013/01/android-loaders-versus-asynctask.html

Anyway, as @codeMagic mentioned, AsyncTask

s android:configChanges="orientation|screenSize"

should be enough for you (it prevents the activity from being recreated when the config changes)

0


source







All Articles