0

I have an Activity with a TextView, and I set the label and color of the TextView each time a background thread invokes a method on the Activity. It works properly until I leave the Activity and re-enter it. In that case, the TextView is not updated because the Runnable that is posted for execution on the UI thread is not invoked. Perhaps I need to implement something in onResume(), but I don't know what that would be.

Here is how the TextView is assigned when the Activity is created:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_manage_nameserver);
        statusView = (TextView) findViewById(R.id.statusNameserverButton);
        ...
}

And here's the method called by the background thread, which updates the TextView:

public void running(boolean running) {
        final int color;
        final String text;
        if (running) {
            color = Color.GREEN;
            text = "Running";
        } else {
            color = Color.RED;
            text = "Stopped";
        }
        statusView.post(new Runnable() {

            @Override
            public void run() {
                statusView.setTextColor(color);
                statusView.setText(text);
            }

        });
}

In the debugger I see that when running() is invoked after I've re-entered the Activity, the Runnable passed to statusView.post() is never invoked. Inspection of the statusView object properties in the debugger shows no difference between the success and failure cases. I don't know what's different after resuming the Activity that would cause the Runnable to not be invoked. I tried re-assigning the TextView object in onResume(), with the same code used to assign it in onCreate(), but that didn't help.

MidnightJava
  • 1,927
  • 2
  • 18
  • 38
  • 1
    First check to see if the Activity after resume is the same one as the original Activity, the original Activity may have been destroyed by Android. Also, check to see if `statusView.post(...)` returns true. – Kai Mar 08 '14 at 09:36
  • Thanks Kai, that enabled me to solve the problem. Please post your comment as an answer so I can accept it and make the solution evident. – MidnightJava Mar 08 '14 at 15:34

1 Answers1

1

First check to see if the Activity after resume is the same one as the original Activity, as the original Activity may have been destroyed by Android. Also, check to see if statusView.post(...) returns true.

Kai
  • 15,284
  • 6
  • 51
  • 82
  • The Activity was being created again each time I navigated to it. The class that updates the Activity with status is a singleton, and I only registered the originally-created Activity on it. This Activity, presumably not garbage-collected because the singleton class retained a reference to it, was being notified; and it no longer had a UI context, I assume. I fixed it by registering the Activity with the singleton on each call to onCreate(). When a new Activity is registered, the singleton disposes the TimerTask that was keeping a reference to the previous Activity instance. – MidnightJava Mar 09 '14 at 02:41
  • 1
    @MidnightJava Using this method, you will always hold 2 instances of the same Activity at the same time at least for a brief moment, which is not desirable. A quick fix would to be store the reference to Activity as a WeakReference: `private WeakReference mainRef = new WeakReference(mainActivity);` and to do this each time you want to use the reference: `Activity mainActivity = mainRef.get(); if (mainActivity != null) {...}` – Kai Mar 09 '14 at 02:50