Since it's not recommended to keep a strong reference to a Context
in a task (the context may get destroyed while the task is still running, but kept in memory by the task), I was wondering if the same applies to Fragments?
Fragments manage their activity reference, and support being retained via setRetainInstance
. Can I assume that e.g. creating a non-static inner AsyncTask in a Fragment is safe in terms of not risking to leak $this
?
By making each screen a separate Fragment, this data passing headache is completely avoided. Fragments always exist within the context of a given Activity and can always access that Activity.
Fragments allow such designs without the need for you to manage complex changes to the view hierarchy. By dividing the layout of an activity into fragments, you become able to modify the activity's appearance at runtime and preserve those changes in a back stack that's managed by the activity.
The Fragment class in Android is used to build dynamic User Interfaces and should be used within the activity. The biggest advantage of using fragments is that it simplifies the task of creating UI for multiple screen sizes. An activity can contain any number of fragments.
It's generally bad methodology to keep references between threads, and an AsyncTask
is something like a thread.
It's okay, as long as you make sure that you dereference it when you are done using it.
Otherwise, you could get memory leaks.
In this case, it's okay because your Fragment
is in the context of AsyncTask
. When the task is done, it will lose that reference.
If this were being done in a Service
, it would be a very bad idea.
Phoenixblade9's answer is correct, but to make it full I'd add one thing.
There's a great replacement for AsyncTask - AsyncTaskLoader, or Loaders generally. It manages its lifecycle according to the context from which it's been called (Activity, Fragment) and implements a bunch of listeners to help you separate the logic of a second thread from the ui thread. And it's generally immune to leaking context.
And don't bother the name - it's good for saving data as well.
As promised I'll post my code for AsyncTaskLoader withg multiple objects returned. The loader goes something like this:
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;
}
In the getYourData()
function I get both the server message code or some other error code and an ArrayList<SomeItem>
. I can use them in my Fragment like this:
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) {
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With