Можно ли хранить ссылки на фрагмент в AsyncTask?

Так как не рекомендуется поддерживать сильную ссылку на Context в задаче (контекст может быть уничтожен, пока задача все еще запущена, но хранится в памяти по задаче), мне было интересно, что же касается Fragments?

Фрагменты управляют ссылкой на свою деятельность, а поддержка сохраняется через setRetainInstance . Могу ли я предположить, что, например, создание нестатической внутренней AsyncTask во Фрагменте безопасно с точки зрения того, что вы не рискуете утечки $this ?

Как правило, это плохая методология для хранения ссылок между потоками, а AsyncTask – это что-то вроде потока.

Все в порядке, если вы убедитесь, что вы разыгрываете его, когда закончите с ним.

В противном случае вы можете получить утечки памяти.

В этом случае это нормально, потому что ваш Fragment находится в контексте AsyncTask . Когда задача будет выполнена, она потеряет эту ссылку.

Если бы это было сделано в Service , это была бы очень плохая идея.

Ответ Phoenixblade9 верен, но чтобы сделать его полным, я добавлю одно.

Есть большая замена AsyncTask – AsyncTaskLoader или Loaders вообще. Он управляет своим жизненным циклом в соответствии с контекстом, из которого он был вызван (Activity, Fragment), и реализует кучу слушателей, чтобы помочь вам отделить логику второго потока от потока 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) { }