5

由于不建议在任务中保留对 a 的强引用Context(在任务仍在运行时上下文可能会被破坏,但由任务保存在内存中),我想知道这是否同样适用于片段?

片段管理它们的活动引用,并支持通过setRetainInstance. 我可以假设例如在 Fragment 中创建一个非静态的内部 AsyncTask 是安全的,不会有泄漏的风险$this吗?

4

2 回答 2

6

保持线程之间的引用通常是不好的方法,并且 anAsyncTask类似于线程。

没关系,只要您确保在完成使用它时取消引用它。

否则,您可能会出现内存泄漏。

在这种情况下,没关系,因为您Fragment的上下文是AsyncTask. 任务完成后,它将丢失该引用。

如果这是在 a 中完成的Service,那将是一个非常糟糕的主意。

于 2012-05-22T19:53:06.183 回答
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) {

}
于 2012-05-22T20:08:38.757 回答