Darksymphony
Darksymphony

Reputation: 2693

android WeakReference of activity

I have an Async Task, where I had a warning that it should be static or leaks might occur.

So I used a WeakReference like this:

 private static class GetContacts extends AsyncTask<String, Void, Boolean> {
    ProgressDialog dialog;
    private WeakReference<Novinky> activityReference;

    GetContacts(Novinky context) {
        activityReference = new WeakReference<>(context);
    }

    @Override
    protected void onPreExecute() {
        // get a reference to the activity if it is still there
        Novinky activity = activityReference.get();
        if (activity == null || activity.isFinishing()) return;
        super.onPreExecute();
        dialog = new ProgressDialog(activity);
        dialog.setMessage("Načítavam");
        dialog.setTitle("Pripájam sa k serveru");
        dialog.show();
        dialog.setCancelable(false);
    }

    @Override
    protected Boolean doInBackground(String... args) {
        HttpHandler sh = new HttpHandler();
        String url = "https://www...";
        String jsonStr = sh.makeServiceCall(url);

        if (jsonStr != null) {
            try {JSONObject jsonObj = new JSONObject(jsonStr);
                JSONArray actors = jsonObj.getJSONArray("result");

                for (int i = 0; i < actors.length(); i++) {
                    JSONObject c = actors.getJSONObject(i);

                    Actors actor = new Actors();

                    actor.setLetter(c.getString("letter"));
                    actor.setNazov(c.getString("name"));
                    actor.setPerex(c.getString("perex"));

                    actorsList.add(actor);
                }

            }  catch (final JSONException e) {
                        Novinky.this.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(Novinky.this.getApplicationContext(),
                                "Chyba dát: " + e.getMessage(),
                                Toast.LENGTH_LONG).show();
                    }
                }); }

            return true;

        } else {
                Novinky.this.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(Novinky.this.getApplicationContext(),
                            "Chyba internetového pripojenia.",
                            Toast.LENGTH_LONG).show();
                }
            });
            return false;
        }
    }

    protected void onPostExecute(Boolean result) {
        // get a reference to the activity if it is still there
        Novinky activity = activityReference.get();
        if (activity == null || activity.isFinishing()) return;
        super.onPostExecute(result);
        dialog.dismiss();
        adapter.notifyDataSetChanged();
    }
}

Now that warning is gone, but I am still fighting with some other errors which came up due my changes.

1/ actorsList.add(actor); - in my for loop now says Non-static field 'actorsList' cannot be referenced from a static context

2/ in catch and else statement where runOnUiThread is placed I have issues with Novinky.this.runOnUiThread - cannot be referenced from a static context

If I simply replace Novinky.this with the WeakReference (activityReference) then it says class name is expected, so not sure how to correctly replace Novinky.this in those threads.

I tried also to use Novinky activity = activityReference.get(); and then use activity.runOnUiThread - this removes the error, but the definition of Novinky activity = activityReference.get(); has then warning This field leaks a context object

3/ The last issue is in my onPostExecute - adapter.notifyDataSetChanged();. The error says: Non-static field 'adapter' cannot be referenced from a static context

UPDATE: I solved it somehow and now I have no errors and the app is running, however still not sure if I solved it correctly:

For 1/ I defined static ArrayList<Actors> actorsList; in the main class.

2/ in catch and else I defined final Novinky activity = activityReference.get();

and then:

activity.runOnUiThread

3/ in onPostExecute I used activity.adapter.notifyDataSetChanged();

Upvotes: 1

Views: 1565

Answers (1)

jbonet
jbonet

Reputation: 76

You should be able to access your instance of the list the same way you access the adapter:

activityReference.get().actorsList

Upvotes: 3

Related Questions