0

I'm relatively new to programming and I am having troubles with an orientation change. I would be thankful for any thoughts.
This is a specific question about the official android documentation, please do not report this question as a duplicate and show me a generic handling runtime thread.

After reading the documentation, I am not sure about the part quoted below.

My question: If I have a timer that shows the current value in a TextView, does this mean I should not use a fragmant to retain the object at all?
Or does it simply mean I should detach the fragmant from the activity entirely?

Android documentation:

Caution: While you can store any object, you should never pass an object that is tied to the Activity, such as a Drawable, an Adapter, a View or any other object that's associated with a Context. If you do, it will leak all the views and resources of the original activity instance. (Leaking resources means that your application maintains a hold on them and they cannot be garbage-collected, so lots of memory can be lost.)

https://developer.android.com/guide/topics/resources/runtime-changes.html#RetainingAnObject

Background information:

My app: (several) interval timers.
I would like to retain the display of the timer if an orientation change occurs during runtime.

I used a hacky solution in the manifestation at first but it lead to problems so figured why not try to solve the problem cleanly.
If I cannot get it done, then most likely I will let the user decide which orientation she or he prefers and then fix it during the runtime of the timer.

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115

1 Answers1

0

Plainly, you should not have a reference to the TextView in the Timer. You can read up on memory leaks, if you want, but that quote gives a good reason... "your application maintains a hold on them and they cannot be garbage-collected, so lots of memory can be lost"

You could use an interface from the Timer, though.

public class MyTimer extends Timer {

    public interface TextChangeListener {
        public void onTextChange(String text);
    }

    private MyTimer.TextChangeListener listener;

    public MyTimer(TextChangeListener listener) {
        this.listener = listener;
    }

    @Override
    public void schedule(...) { // TODO: Pick which one to override
        super.schedule(...); // TODO: Use the same params
        if (listener != null) {
            listener.onTextChange("Some text");
        }
    }
}

Then, just implement that interface and start your timer

public class MainActivity extends AppCompatActivity
      implements MyTimer.TextChangeListener  {

    private TextView textView;

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.activity_main);
        // TODO: textView = findViewById(R.id.textView);
        Timer t = new MyTimer(this); // 'this' refers to the interface
        // TODO: Start timer
    }

    public void onTextChange(String text) {
        textView.setText(text);
    }

}

If you need to handle orientation changes, then I believe that link discusses making use of the onSaveInstanceState and onRestoreInstanceState methods

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
  • That's helpful - thanks!. I added them as a final TextView as paremeters (didn't seem to be great but couldn't think of anything else). I'll to change my code to use an interface as you suggested - thanks so far! – LongDoo123 Test Oct 03 '16 at 08:17
  • I'm sorry for being an idiot but could you give me more details on "public void schedule(...) { // TODO: Pick which one to override ". I am lost here :( – LongDoo123 Test Oct 03 '16 at 12:04
  • You said you were using a Timer class. I looked up the only Timer class I saw in the Android SDK. There's multiple schedule methods with various parameters – OneCricketeer Oct 03 '16 at 13:22