5

タスク内でaへの強い参照を保持することは推奨されないためContext(タスクの実行中にコンテキストが破棄される可能性がありますが、タスクによってメモリに保持されます)、同じことがフラグメントにも当てはまるかどうか疑問に思いました。

フラグメントはアクティビティ参照を管理し、を介して保持されることをサポートしsetRetainInstanceます。たとえば、フラグメントに非静的な内部AsyncTaskを作成することは、リークのリスクがないという点で安全であると想定できます$thisか?

4

2 に答える 2

6

スレッド間の参照を保持することは一般的に悪い方法であり、AsyncTaskスレッドのようなものです。

使い終わったら、必ず逆参照する限り、問題ありません。

そうしないと、メモリリークが発生する可能性があります。

この場合、あなたFragmentはのコンテキストにあるので問題ありませんAsyncTask。タスクが完了すると、その参照は失われます。

これがで行われている場合Service、それは非常に悪い考えです。

于 2012-05-22T19:53:06.183 に答える
2

Phoenixblade9の答えは正しいですが、それを完全にするために1つ追加します。

AsyncTaskの優れた代替品があります-AsyncTaskLoader、または一般的にローダー。呼び出されたコンテキスト(アクティビティ、フラグメント)に従ってライフサイクルを管理し、2番目のスレッドのロジックをUIスレッドから分離するのに役立つ一連のリスナーを実装します。そして、それは一般的にリークコンテキストの影響を受けません。

また、名前を気にしないでください。データの保存にも適しています。


約束どおり、複数のオブジェクトが返されたAsyncTaskLoaderのコードを投稿します。ローダーは次のようになります。

public class ItemsLoader extends AsyncTaskLoader<HashMap<String, Object>>{

HashMap<String, Object> returned;
ArrayList<SomeItem> items;
Context cxt;

public EventsLoader(Context context) {
    super(context);
    //here you can initialize your vars and get your context if you need it inside
}

@Override
public HashMap<String, Object> loadInBackground() {


    returned = getYourData();

    return returned;

}

@Override
public void deliverResult(HashMap<String, Object> returned) {
    if (isReset()) {
        return;
    }

    this.returned = returned;

    super.deliverResult(returned);
}

@Override
protected void onStartLoading() {
    if (returned != null) {
        deliverResult(returned);
    }

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

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

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

    onStopLoading();

    returned = null;
}

関数ではgetYourData()、サーバーメッセージコードまたはその他のエラーコードと。の両方を取得しますArrayList<SomeItem>。私は次のようにフラグメントでそれらを使用できます:

public class ItemListFragment extends ListFragment implements LoaderCallbacks<HashMap<String, Object>>{

private LoaderManager lm;

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    lm = getLoaderManager();

    Bundle args = new Bundle();
args.putInt("someId", someId);
lm.initLoader(0, args, this);
}


@Override
public Loader<HashMap<String, Object>> onCreateLoader(int arg0, Bundle args) {
    ItemsLoader loader = new ItemsLoader(getActivity(), args.getInt("someId"));
    return loader;
}

@Override
public void onLoadFinished(Loader<HashMap<String, Object>> loader, HashMap<String, Object> data) {

    if(data!=null){ if(data.containsKey("items")){ 
        ArrayList<SomeItem> items = (ArrayList<EventItem>)data.get("items");

    } else { //error
        int error = 0;
        if(data.containsKey("error")){
            error = (Integer) data.get("error");
        }
            }

}

@Override
public void onLoaderReset(Loader<HashMap<String, Object>> arg0) {

}
于 2012-05-22T20:08:38.757 に答える