由于不建议在任务中保留对 a 的强引用Context
(在任务仍在运行时上下文可能会被破坏,但由任务保存在内存中),我想知道这是否同样适用于片段?
片段管理它们的活动引用,并支持通过setRetainInstance
. 我可以假设例如在 Fragment 中创建一个非静态的内部 AsyncTask 是安全的,不会有泄漏的风险$this
吗?
由于不建议在任务中保留对 a 的强引用Context
(在任务仍在运行时上下文可能会被破坏,但由任务保存在内存中),我想知道这是否同样适用于片段?
片段管理它们的活动引用,并支持通过setRetainInstance
. 我可以假设例如在 Fragment 中创建一个非静态的内部 AsyncTask 是安全的,不会有泄漏的风险$this
吗?
保持线程之间的引用通常是不好的方法,并且 anAsyncTask
类似于线程。
没关系,只要您确保在完成使用它时取消引用它。
否则,您可能会出现内存泄漏。
在这种情况下,没关系,因为您Fragment
的上下文是AsyncTask
. 任务完成后,它将丢失该引用。
如果这是在 a 中完成的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) {
}