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
android android-activity android-asynctask loader


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 to share


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 to share


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 to share


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 to share







All Articles
Loading...
X
Show
Funny
Dev
Pics