有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Android AsyncTaskLoader未启动loadInBackground?

我试图在Android上实现一个加载程序示例,但无法让它启动加载程序。我正在使用以下代码。它将命中“创建加载程序”,但永远不会到达“加载已开始”日志消息。我是不是错过了一个我需要的电话

活动:

    public class TestingZoneActivity extends ListActivity implements LoaderCallbacks<ArrayList<Content>>{

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);

            getLoaderManager().initLoader(0, null, this);
        }

        @Override
        public Loader<ArrayList<Content>> onCreateLoader(int id, Bundle args) {
            Log.e("TEST", "Create Loader");
            return new ImageLoader(this);
        }

        @Override
        public void onLoadFinished(Loader<ArrayList<Content>> loader, ArrayList<Content> data) {
            setListAdapter(new ImageAdapter(this, data));
        }

        @Override
        public void onLoaderReset(Loader<ArrayList<Content>> loader) {
            setListAdapter(null);
        }
    }

加载器:

    public class ImageLoader extends AsyncTaskLoader<ArrayList<Content>> {

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

        @Override
        public ArrayList<Content> loadInBackground() {
            Log.e("TEST", "Loading started");
        }

    }

共 (6) 个答案

  1. # 1 楼答案

    如果您使用的是自定义加载程序,则可以保存最后一个数据引用,并通过getter使其可用。当用户旋转屏幕时,可以从getLoaderManager()获取加载程序。方法,然后返回引用。在我的测试中,我注意到StartLoader一直到CustomLoader。onload已完成,但结果永远不会传递给活动。装载完成。我怀疑活动引用在旋转时丢失了。顺便说一句,创建加载程序的好处在于它们通过LoaderManager是持久的。把它看作是无头碎片的另一种味道。。哈哈

    Loader loader  =  getLoaderManager().getLoader(LOADER_ID);
    
    if( loader == null )
    {
        getLoaderManager().initLoader(LOADER_ID, null, MyActivity.this );
    }
    else
    {
        listAdapter.addAll(((CustomLoader) loader).getLastData());
    }
    
  2. # 2 楼答案

    因为这里没有一个答案(除了公认的答案)能单独帮助我解决这个问题,下面是它对我的作用

    我不认为接受的答案是正确的解决方案,因为它会导致调用loadInBackground()的次数超过必要的次数,即在方向更改时,在加载程序中正确重写以下方法时也不会发生这种情况:

    @Override
    public void deliverResult(final List<Participant> data) {
        participants = data;
    
        if (isStarted()) {
            super.deliverResult(data);
        }
    
    }
    
    @Override
    protected void onStartLoading() {
        if (takeContentChanged() || participants == null) {
            forceLoad();
        }
    }
    
  3. # 3 楼答案

    覆盖loadInBackground()是不够的

    看看http://developer.android.com/reference/android/content/AsyncTaskLoader.html上的AppListLoader

    至少将这两种方法添加到加载程序:

            @Override
            protected void onStartLoading() {
                if (takeContentChanged())
                    forceLoad();
            }
    
            @Override
            protected void onStopLoading() {
                cancelLoad();
            }
    

    并从其构造函数中调用onContentChanged()

  4. # 4 楼答案

    我在使用兼容性库时也遇到了同样的问题。 我通过调用forceLoad解决了这个问题

    getLoaderManager().initLoader(0, null, this).forceLoad();
    

    很明显,AsyncLoader的文档是缺乏的,这个问题也存在于蜂巢上。更多信息请参见here

    AsyncTaskLoader的官方example也在调用forceLoad(),所以这不是一个bug,但我仍然认为这种行为不是很直观

  5. # 5 楼答案

    我发现上面的每个解决方案都有问题,特别是当应用程序在屏幕关闭时启动,并且加载需要几分钟的时候

    以下是我的解决方案(基于this):

    https://stackoverflow.com/a/22675607/878126

  6. # 6 楼答案

    rrayst的建议非常简洁。如果您这样编写方法:

    protected void onStartLoading() {
        forceLoad();
    }
    

    您会注意到,当一个子活动出现,然后返回到父活动时,onStartLoading(因此loadInBackground)再次被调用

    你能做什么? 在构造函数内将内部变量(mContentChanged)设置为true;然后在onStartLoading内检查此变量。只有当它为真时,才开始真正加载:

    package example.util;
    
    import android.content.Context;
    import android.support.v4.content.AsyncTaskLoader;
    
    public abstract class ATLoader<D> extends AsyncTaskLoader<D> {
    
        public ATLoader(Context context) {
            super(context);
            // run only once
            onContentChanged();
        }
    
        @Override
        protected void onStartLoading() {
            // That's how we start every AsyncTaskLoader...
            // -  code snippet from  android.content.CursorLoader  (method  onStartLoading)
            if (takeContentChanged()) {
                forceLoad();
            }
        }
    
        @Override
        protected void onStopLoading() {
            cancelLoad();
        }
    }