1

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

UI 有几个按钮。

用户单击其中一个,应用程序将请求发送到服务器(休息调用) 当请求正在处理时,显示微调器(大约 10 秒)

现在它使用 AsyncTask - 所以如果应用程序将纵向更改为横向 - 活动会重新启动并且我会丢失该过程

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

这会导致很多异常——当 LoaderManager 向未启动项发送事件时

有什么解决办法吗?

一些评论: - 10 秒只是一个例子 - 将用户锁定到一个方向不是一种选择 - 服务对于简单的休息调用来说太过分了

4

4 回答 4

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;
        }
    }
}
于 2013-05-29T02:16:27.710 回答
0

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

android:configChanges="orientation"

savedInstanceState()

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

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

于 2013-05-29T01:08:09.860 回答
0

如果您AsyncTask为此使用 a ,您可能希望使用 aService代替或使用onRetainNonConfigurationInstanceFragment.setRetainInstance允许AsyncTask通过配置更改。

或禁用配置更改:我过去曾成功使用过它。

于 2013-05-29T01:08:52.950 回答
0

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

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

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

于 2013-08-13T15:21:42.517 回答