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