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 からすべての LoaderManagers (それ自体またはそのサブフラグメント) をロードします。

    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に属するローダーを起動しようとすると失敗します。

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 値に注意してください。

そして、この問題を解決するには2つの方法があります。

  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代わりに使用してください。getLoaderLoaderforceLoad()

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 に答える