1

onCreate() でローダーを初期化し、ボタンが押されたときにローダーを再起動する単純なコード。Android ドキュメント getLoaderManager().restartLoader() については、新しいローダーを開始するか、このマネージャーで既存のローダーを再起動する必要があります。しかし、ボタンを押して restartLoader を呼び出すたびに、新しい AbstractLoader が作成されます。

Android ドキュメントの LoaderManager.restartLoader()

public class MainActivity extends Activity implements LoaderCallbacks<String>{

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    getLoaderManager().initLoader(1, null, this); //id is the same
}

@Override
public android.content.Loader<String> onCreateLoader(int id, Bundle args) {
    return new AbstractLoader(this);
}

@Override
public void onLoadFinished(android.content.Loader<String> arg0, String arg1) {
    // TODO Auto-generated method stub
}

@Override
public void onLoaderReset(android.content.Loader<String> arg0) {
    // TODO Auto-generated method stub
    
}

public void click(View v){ //button clicked
    getLoaderManager().restartLoader(1, null, this); //id is the same
}
}

AbstractLoader コードは次のとおりです。

public class AbstractLoader extends AsyncTaskLoader<String>{

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

 String mResult;

    @Override public String loadInBackground() {
        if (mResult == null) {
            mResult = "Test_String";
        }


        return mResult;
    }

    @Override public void deliverResult(String apps) {
        if (isReset()) {
            if (apps != null) {
                onReleaseResources(apps);
            }
        }
        mResult = apps;

        if (isStarted()) {
            super.deliverResult(apps);
        }

    }

    @Override protected void onStartLoading() {
        Log.e("!LOG!", "onStartLoading " + mResult); //mResult is null each time
        if (mResult != null) {
            deliverResult(mResult);
        }


        if (takeContentChanged() || mResult == null) {
            forceLoad();
        }
    }

    @Override protected void onStopLoading() {
        cancelLoad();
    }

    @Override public void onCanceled(String apps) {
        super.onCanceled(apps);

        onReleaseResources(apps);
    }

    @Override protected void onReset() {
        super.onReset();

        onStopLoading();

        if (mResult != null) {
            onReleaseResources(mResult);
            mResult = null;
        }
    }

    protected void onReleaseResources(String apps) {
    }

}

以前の結果を返したい別のケースでは、5 分に 1 回だけデータをロードしたいので、mResult 値が必要です。私の質問は、initLoader を使用して onCreate で同じ ID のローダーを作成した場合でも、「restart」でローダーが再作成されるのはなぜですか。ありがとう

4

1 に答える 1

1

メソッド名に基づいて正確に何が起こるかは曖昧ですが、ドキュメントのこの行は、あなたが説明する動作を説明していると思います:

同じ ID を持つローダーが以前に開始されている場合、新しいローダーが作業を完了すると、自動的に破棄されます。古いローダーが破棄される前に、コールバックが配信されます。

これが内部でどのように機能するかは正確にはわかりませんが、このrestartLoader()メソッドは新しい を作成し、新しいデータを取得してから、古いのデータがなくなる前にLoaderマージしたり、古いデータとやり取りしたりできるように思われます。新しい情報のフェッチのみを許可するものとはLoader対照的です。initLoader

あなたを助けることができる方法はonContentChanged()だと思いますLoader. LoaderManagergetLoader(int)メソッドを使用して、Loader開始した への参照を取得し、そのメソッドを呼び出して更新をトリガーできます。

編集: 当初はの代わりにstartLoading()onContentChanged()を使用することを提案していましたが、ドキュメントによると、LoaderManager. forceLoad()も可能ですがonContentChanged()、過去に成功したことがあるので、使用することをお勧めします。

于 2013-10-09T21:12:05.457 に答える