【问题标题】:Will LoaderManager.restartLoader() always result in a call to onCreateLoader()?LoaderManager.restartLoader() 是否总是会导致调用 onCreateLoader()?
【发布时间】:2014-02-10 18:20:01
【问题描述】:

LoaderManager有这个方法restartLoader()

public abstract Loader<D> restartLoader (int id, Bundle args, LoaderCallbacks<D> callback)

在这个管理器中启动一个新的或重新启动一个现有的加载器,注册回调,并且(如果活动/片段当前已启动)开始加载它。如果之前已经启动了具有相同 id 的加载器,它将在新加载器完成其工作时自动销毁。回调将在旧加载器被销毁之前传递。

基于the dev guide,我知道确实,对onCreateLoader 的调用总是来自restartLoader()

重新启动加载器

...

要丢弃旧数据,请使用 restartLoader()。例如,当用户查询发生变化时,SearchView.OnQueryTextListener 的这个实现会重新启动加载程序。加载程序需要重新启动,以便它可以使用修改后的搜索过滤器进行新的查询:

public boolean onQueryTextChanged(String newText) {
    // Called when the action bar search text has changed.  Update
    // the search filter, and restart the loader to do a new query
    // with this filter.
    mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
    getLoaderManager().restartLoader(0, null, this);
    return true;
}

public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    // NOTE: The Loader is instantiated with the user's query

    Uri baseUri;       
    if (mCurFilter != null) {
        baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
                  Uri.encode(mCurFilter));
    } else {
        baseUri = Contacts.CONTENT_URI;
    }

    // Now create and return a CursorLoader that will take care of
    // creating a Cursor for the data being displayed.
    String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("
            + Contacts.HAS_PHONE_NUMBER + "=1) AND ("
            + Contacts.DISPLAY_NAME + " != '' ))";
    return new CursorLoader(getActivity(), baseUri,
            CONTACTS_SUMMARY_PROJECTION, select, null,
            Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
}

在示例中,onCreateLoader 是唯一将有关用户查询的信息传递给加载器的位置(在实例化时)。然而,文档说“启动一个新的或重新启动一个现有的加载程序”让我失望。

【问题讨论】:

    标签: android android-loadermanager android-loader


    【解决方案1】:

    您的问题的简单答案是肯定的,对 restartLoader() 的调用将再次调用 onCreateLoader()。

    您可以并行启动多个加载程序(假设您有两个 SimpleCursorAdapter 要填充),例如:

    getLoaderManager().initLoader(0, null, this);  //id = 0
    getLoaderManager().initLoader(1, null, this);  //id = 1
    

    然后加载器管理器为每个 id 调用 onCreateLoader(返回的加载器然后由加载器管理器异步构建):

    public Loader<Cursor> onCreateLoader(int id, Bundle args)
    {
        if (id == 0)
            //return a Loader<Cursor> for id 0
        else if (id == 1)
            //return a Loader<Cursor> for id 1
    }
    

    加载器管理器将生成的加载器传递给 onLoadFinished:

    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor)
    {
        if (loader.getId() == 0)
            //cursor was returned from onCreateLoader for id 0
            //perhaps do swapCursor(cursor) on an adapter using this loader
        else if (loader.getId() == 1)
            //cursor was returned from onCreateLoader for id 1
            //perhaps do swapCursor(cursor) on an adapter using this loader
    }
    

    当你随后调用重启加载器时:

    getLoaderManager().restartLoader(0, null, this);  //id = 0
    

    ...onLoaderReset 首先被调用:

    public void onLoaderReset(Loader<Cursor> loader)
    {
        if (loader.getId() == 0)
            //perhaps do swapCursor(null) on an adapter using this loader
        else if (loader.getId() == 1)
            //perhaps do swapCursor(null) on an adapter using this loader
    }
    

    ...接着是对 onCreateLoader 的新调用。因此,在这方面,onCreateLoader 既用于启动全新的加载器,也用于重置现有加载器。

    【讨论】:

    • 我很想知道您为什么会这样认为?这是加载器的全部要点,与 ContentProvider/Datasource 进行异步交互。可能会阻塞 UI 的长时间运行的任务在 onCreateLoader 中运行 - LoaderManager 在后台运行该部分。
    • 是的,是的,AsyncTaskLoader 的 loadInBackBackground 部分肯定在后台线程上运行,但我认为 onCreateLoader 在 UI 线程上:Clients of loaders should as a rule perform any calls on to a Loader from the main thread of their process (that is, the thread the Activity callbacks and other things occur on). -- 与实例化 AsyncTask 相当,这是我的推理。
    • 从客户端/主线程对 Loader 的调用是 .initLoader() 调用。然后加载器在后台运行 onCreateLoader。
    • 使用这个:android.os.Process.getThreadPriority(android.os.Process.myTid());似乎 onCreateLoader 在 UI 线程上运行。我还在 onCreateLoader 中添加了一些 UI 更新,它可以正常工作。
    • @ANemati 谢谢;再看一遍你是对的。 onCreateLoader 确实在 UI 线程上运行——它返回的加载器是由加载器管理器异步构建的。我已编辑我的答案以消除不准确之处。
    猜你喜欢
    • 1970-01-01
    • 2019-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    • 1970-01-01
    • 2020-08-13
    • 1970-01-01
    相关资源
    最近更新 更多