【问题标题】:Delaying Loaders延迟加载程序
【发布时间】:2012-05-09 17:24:07
【问题描述】:

是否总是需要在 Fragment 中从 onCreate 初始化加载器?如果加载器的关键参数依赖于另一个加载器的结果怎么办?

即您有 2 个加载器:LoaderA 和 LoaderB。 LoaderB 需要 LoaderA 的结果才能运行。 LoaderA 和 LoaderB 都在片段的 onCreate 中初始化,但 LoaderB 没有给定参数,因此它故意失败。 一旦 LoaderA 完成,LoaderB 会使用新参数重新启动,以便它可以执行所需的请求。

片段中的加载器初始化:

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    getLoaderManager().initLoader(LOADER_A, new Bundle(), this);
    getLoaderManager().initLoader(LOADER_B, null, mLoaderBCallback);
}

在片段中回调 LOADER_A:

@Override
public Loader<MyResultObject> onCreateLoader(int id, Bundle args) { 
    return new LoaderA(getActivity(), args);
}

@Override
public void onLoadFinished(Loader<MyResultObject> loader, final MyResultObject result) {
    if (result != null) {
        Bundle args = new Bundle();
        args.putInt("id", result.getId());

        getLoaderManager().restartLoader(LOADER_B, args, mLoaderBCallback);
    }
}

fragment中mLoaderBCallback的定义:

private LoaderBCallback mLoaderBCallback = new LoaderBCallback();

(LoaderBCallback 的实现并不重要,它只是标准的 LoaderCallbacks 接口,它创建一个 LoaderB 的实例并在加载器完成时进行处理。)

LoaderB 类(请原谅这个类定义的任何潜在编译器错误,它只是一个示例):

public class LoaderB<List<AnotherResultObject>> extends AsyncTaskLoader<List<AnotherResultObject>> { 
    private Bundle mArgs;

    public LoaderB(Context context, Bundle args) {
        super(context);
        mArgs = args;
    }

    @Override
    public List<AnotherResultObject> loadInBackground() {
        if (mArgs == null) {
            // bail out, no arguments.
            return null;
        }


        // do network request with mArgs here
        return MyStaticClass.performAwesomeNetworkRequest(mArgs);
    }

    // boiler plate AsyncTaskLoader stuff here
    ...... 

}

有没有更好的方法?我们可以不使用 LoaderB 的 initLoader 吗?

编辑:我的印象是加载程序总是必须在 onCreate 中初始化,以便它们可以处理配置更改。这可能仅适用于活动中的加载程序。在 Fragments 中创建的 loader 无论在哪里初始化都会得到管理吗?

【问题讨论】:

    标签: android


    【解决方案1】:

    您可以在代码中的任何位置初始化加载程序。

    在您的情况下,您应该将 onLoadFinished 中的 restartLoader 替换为 initLoader。只需从 LOADER_B 的 onActivityCreated 中删除 initLoader

    此外,您应该在 onLoadFinished 中检查加载程序的 ID,以便知道哪个加载程序完成了。

    编辑:您正在为LOADER_B 回调使用单独的侦听器,因此我的 ID 检查点在那里被击败了.. 但无论如何.. 如果您愿意,可以将它们组合成一个

    @Override
    public void onLoadFinished(Loader<MyResultObject> loader, final MyResultObject result) {
        switch (loader.getId())
        {
          case LOADER_A:
             if (result != null) {
                 Bundle args = new Bundle();
                 args.putInt("id", result.getId());
                 // i put "this" as the callback listener. you can use your custom one here if you want
                 getLoaderManager().initLoader(LOADER_B, args, this);
             }
             break;
          case LOADER_B:
             //do whatever
             break;
    }
    

    【讨论】:

    • 如果你不在某个重要的地方初始化加载器,加载器是否还能在生命周期事件(例如方向改变)中幸存下来?
    • 应该的。加载器结果通过方向变化保持不变。
    猜你喜欢
    • 1970-01-01
    • 2013-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多