1

I'm running an AsyncTask to retrieve some info via HTTP.

I'm calling this method from my main activity (do_get_from_url() is triggered by a button click):

private void do_get_from_url() {
    new getFromURL(this).execute();
}

The class that this calls is in the same .java file and starts as follows:

class getFromURL extends AsyncTask<Void, Void, String> {

  private MainActivity activity;

  getFromURL(MainActivity activity){
    this.activity = activity;
  }

  ...other code here...

  String linkURL = activity.link_url.getText().toString();

  String getFromURLrequestURL = activity.getString(R.string.short_url_request_url_base);

  ...other code here...

}

It seems that I need to use activity in order to access both the string resources and the UI element link_url from the main activity BUT the line this.activity = activity displays a warning in Android Studio that it is leaking a context.

Is there any way to avoid this?

Fat Monk
  • 2,077
  • 1
  • 26
  • 59
  • Related https://stackoverflow.com/questions/39773631/static-context-warning and https://stackoverflow.com/questions/48127346/android-studio-say-static-field-will-leak-contexts – AskNilesh Aug 21 '18 at 11:43
  • I already thought it sounded like a leak to avoid, but that's pretty scary stuff... A bad error to leave in place. – Fat Monk Aug 21 '18 at 13:12

2 Answers2

1

Yes, there is. Correct way is to use a WeakRefrence like this

WeakReference<MainActivity> parent;

GetFromURL(MainActivity activity){
   parent = new WeakReference(activity);
}

...other code here...

String linkURL = parent.get().link_url.getText().toString();

String getFromURLrequestURL = parent.get().getString(R.string.short_url_request_url_base);

...other code here...

DNA.h
  • 823
  • 8
  • 17
  • The `patent = new WeakReference` line now gives an `Unchecked assignment` and an `Unchecked call` warning... Seems to work though... – Fat Monk Aug 21 '18 at 13:02
1

Root cause: You are passing an activity as a context to a background thread. So the thread will keep a reference to the activity. As long as the thread running, the activity cannot be destroyed (by calling finish() method or users press back key to finish the activity). The term leak simply mean when an object or instance no longer used but the system cannot reclaim memory where they live on.

Solution: In Android you can use an API called WeakReference, Simply it will keep a weak reference to your object (in this case your activity), so when the activity get destroyed, it will not keep the reference anymore.

getFromURL.java

class getFromURL extends AsyncTask<Void, Void, String> {

    private WeakReference<MainActivity> mainActivityWeakReference;

    getFromURL(MainActivity activity){
        mainActivityWeakReference = new WeakReference<>(activity);
    }

  ...other code here...

    MainActivity activity = mainActivityWeakReference.get();
    // Always check this to make sure the activity haven't got destroyed yet.
    if (activity != null) {
        String linkURL = activity.link_url.getText().toString();
        String getFromURLrequestURL = activity.getString(R.string.short_url_request_url_base);
    }

  ...other code here...

}
Son Truong
  • 13,661
  • 5
  • 32
  • 58