9

我想用一个演示来展示这一点:

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

    Button button = (Button) findViewById(R.id.button1);
    button.setOnClickListener(buttonClickListener);
}

private OnClickListener buttonClickListener = new OnClickListener() {

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        startMyLoader();
    }

};

private void startMyLoader() {
    getLoaderManager().destroyLoader(0);
    getLoaderManager().restartLoader(0, null, myLoaderListener);
}

/**
 * The listener for the group metadata loader.
 */
private final LoaderManager.LoaderCallbacks<Cursor> myLoaderListener 
    = new LoaderCallbacks<Cursor>() {

    @Override
    public CursorLoader onCreateLoader(int id, Bundle args) {
        return new CursorLoader(LoaderDemoActivity.this, 
        ContactsContract.Contacts.CONTENT_URI, 
        null, null, null, null);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        cursor.moveToPosition(-1);
        if (cursor.moveToNext()) {
            Context context = getApplicationContext();
            CharSequence text = "Load finished!";
            int duration = Toast.LENGTH_SHORT;

            Toast toast = Toast.makeText(context, text, duration);
            toast.show();
        }
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
    }
};
enter code here

方向改变后,点击按钮,可以调用onCreateLoader,但不会调用onLoadFinished。

似乎很奇怪。

提前感谢您的帮助。

4

5 回答 5

14

我遇到了同样的问题。请尝试在 onCreate 中调用 this.getSupportLoaderManager()。它解决了我的问题。希望它也能帮助你

于 2012-07-16T08:48:31.157 回答
5

我想我找到了原因。

在 Activity onCreate 中,它将从 NonConfigurationInstances 加载所有 LoaderMangers(它自己的或它的子 Fragments)。

    if (mLastNonConfigurationInstances != null) {
        mAllLoaderManagers = mLastNonConfigurationInstances.loaders;
    }

而在Activity onStart 中,它会尝试启动自己的LoaderManger。

    if (!mLoadersStarted) {
        mLoadersStarted = true;
        if (mLoaderManager != null) {
            mLoaderManager.doStart();
        } else if (!mCheckedForLoaderManager) {
            mLoaderManager = getLoaderManager(-1, mLoadersStarted, false);
        }
        mCheckedForLoaderManager = true;
    }

但是配置更改后,mLoaderManager == null,所以它不会启动它。这就是问题所在!如果你尝试启动属于这个loaderManager的loader,它会失败。

void installLoader(LoaderInfo info) {
    mLoaders.put(info.mId, info);
    if (mStarted) {
        // The activity will start all existing loaders in it's onStart(),
        // so only start them here if we're past that point of the activitiy's
        // life cycle
        info.start();
    }
}

注意在 LoaderManager 启动时将设置为“true”的 mStarted 值。

有两种方法可以解决这个问题。

  1. 在 onCreate() 中调用 getLoaderManger(),它将重新分配 mLoaderManager 并使其准备好在后续的 onStart() 中启动。

    public LoaderManager getLoaderManager() { if (mLoaderManager != null) { return mLoaderManager; } mCheckedForLoaderManager = true; mLoaderManager = getLoaderManager(-1, mLoadersStarted, true); 返回 mLoaderManager;}

  2. 让加载器位于片段中。因为在 Fragments 的 onStart() 中,会启动自己的 LoaderManager。

    if (!mLoadersStarted) { mLoadersStarted = true; if (!mCheckedForLoaderManager) { mCheckedForLoaderManager = true; mLoaderManager = mActivity.getLoaderManager(mIndex, mLoadersStarted, false); } if (mLoaderManager != null) { mLoaderManager.doStart(); } }

于 2012-04-17T04:18:31.593 回答
3

你不需要(也不应该)销毁你Loader的来重新加载它。Loader类旨在可重用。

改为使用initLoader。例如。:

getLoaderManager().initLoader(0, null, myLoaderListener);

如果你想强制重新加载已经注册的加载器:

getLoaderManager().getLoader(0).forceLoad();

如果您不确定Loader在配置更改事件发生后实例是否已经存在,请使用initLoader而不是getLoader检索您Loader可以调用的实例forceLoad()

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

如果您使用支持库,那么forceLoad即使在第一次实例化后也可以使用 - 可能存在错误 - 我提醒自己在这个论坛上有一些关于它的问题 - 尝试搜索旧帖子。

于 2012-04-16T21:44:15.043 回答
1

在活动中调用加载程序之前,请确保您没有savedStateInfo在使用片段时进行检查onCreate

@Override
public void onCreate(Bundle savedInstanceState) {

    // used to not overlap fragments
    if (savedInstanceState != null) {
        return null;
    }

    loadFragments();

    getSupportLoaderManager().restartLoader(LISTS_LOADER, null, this);
}

如果您无论如何都需要检查savedInstanceState片段,您可以检查应该在加载器完成加载后创建的任何类变量,因为活动在旋转时被破坏,但在旋转时从先前的状态上升。

于 2012-11-28T22:23:07.893 回答
0

来自android的开发站点

“在配置更改后重新创建时,它们会自动重新连接到最后一个加载器的光标。因此,它们不需要重新查询其数据。”

据我了解,即使我们明确启动加载程序,加载程序也不会启动。因为我们调用的destroy实际上应该onLoaderReset()在它被销毁后调用。但是一旦方向改变,就不会调用该方法,而是在之前调用该方法。

我仍然可能是错的。这是我的假设。进一步讨论将不胜感激。

于 2012-04-16T10:27:27.340 回答