按钮点击Android Loader与AsyncTask

时间:2013-05-29 01:00:29

标签: android android-activity android-asynctask loader

我有一个活动,在加载时不需要来自服务器的数据 - 只需ui的简单初始化

UI有几个按钮。

用户点击其中一个,app向服务器发送请求(休息通话) 请求处理时显示微调器(约10秒)

现在它使用AsyncTask - 所以如果应用程序将纵向更改为横向 - 活动重新启动并且我松开了进程

第二个选项是使用Loader - 问题是它是在按钮点击时启动 - 而不是在活动开始时

这导致许多例外 - 当LoaderManager将事件发送到非启动项

有没有解决方案?

几条评论: - 例如10秒 - 将用户锁定到一个方向不是一个选项 - 简单的休息电话服务是过度的

4 个答案:

答案 0 :(得分:3)

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's 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's response
            return result;
        }
    }
}

答案 1 :(得分:0)

首先,您可以通过声明来消除orienatation更改问题

android:configChanges="orientation"

savedInstanceState()

但真正的问题是让用户盯着旋转器10秒钟。大多数用户对此没有足够的耐心。我不知道你的应用程序在做什么,所以很难给出准确的建议,但我可以说你需要在AsyncTask中做你的网络内容,但允许用户做其他事情

您可以允许用户在AsyncTask完成时执行其他操作或将该代码放入[服务(http://developer.android.com/guide/components/services.html)中。无论哪种方式,都不要让你的用户盯着屏幕进行10秒的旋转......他们不会长时间成为你的用户

答案 2 :(得分:0)

如果您使用的是AsyncTask,则可能需要使用Service或使用onRetainNonConfigurationInstanceFragment.setRetainInstanceAsyncTask完成配置更改。

或者禁用配置更改:我过去曾使用过这种方法并取得了一些成功。

答案 3 :(得分:0)

这是一篇关于这个主题的好文章:

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

无论如何,正如@codeMagic所提到的,AsyncTask android:configChanges="orientation|screenSize"应该足够(它可以防止在配置更改时重新创建活动)