Is this runnable safe from memory leak?

I am new to Java and created a simple Java Android fragment where in Runnable after 1.5 seconds I change the TextView from Hello World to Hola Mundo . It works flawlessly, basically WeakReference should prevent this memory leak correctly? I have doubts that with any orientation of the device there is no memory leak. I would really like to check it out, but I was not able to change the orientation in my emulated Android.

This is the code:

 package com.example.helloworld; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.widget.TextView; import android.util.Log; import java.lang.ref.WeakReference; public class HelloWorldActivity extends Activity { private Handler h = new Handler(); private static TextView txtview; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); txtview = (TextView) findViewById(R.id.mainview); h.postDelayed(new WeakRunnable(txtview),1500); } private static final class WeakRunnable implements Runnable { private final WeakReference<TextView> mtextview; protected WeakRunnable(TextView textview){ mtextview = new WeakReference<TextView>(textview); } @Override public void run() { TextView textview = mtextview.get(); if (textview != null) { txtview.setText("Hola Mundo"); textview = null; // No idea if setting to null afterwards is a good idea } Log.d("com.example.helloworld", "" + textview); } } } 

EDIT

This is safe from memory leaks, but a few answers also related to blocking user interface threads. Actually this code starts the handler in the main thread (UI). To create a new stream, I manually create the stream as follows:

 package com.example.helloworld; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.widget.TextView; import android.util.Log; import java.lang.ref.WeakReference; public class HelloWorldActivity extends Activity { private static TextView txtview; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); txtview = (TextView) findViewById(R.id.mainview); Thread t = new Thread(new WeakRunnable(txtview)); t.start(); } private static final class WeakRunnable implements Runnable { private final WeakReference<TextView> mtextview; protected WeakRunnable(TextView textview){ mtextview = new WeakReference<TextView>(textview); } @Override public void run() { TextView textview = mtextview.get(); if (textview != null) { /* try { Thread.sleep(1500); } catch (InterruptedException e) { e.printStackTrace(); } */ txtview.setText("Hola Mundo"); textview = null; } Log.d("com.example.helloworld", "" + Thread.currentThread().getName()); // Outputs "Thread-<num>" if not running on UI thread } } } 

Now the problem is that I just can’t delay the spawned thread, otherwise it will work.

It:

 try { Thread.sleep(1500); } catch (InterruptedException e) { e.printStackTrace(); } 

makes the application private, and I don’t understand why. Something tells me that I delay it wrong.

EDIT2

Thanks to the @EugenMatynov link, give me: update ui from another thread in android I understood why the application closed. It all comes down to the fact that you cannot call user interface methods from threads other than the main thread. and it’s bad practice to update the user interface from another thread.

+5
source share
4 answers

I think your code will leak if you use:

 private static Handler h = new Handler(); 

or

 txtview.postDelayed(new WeakRunnable(txtview),1500); 

because you saved the view as a WeakReference. method:

 txtview.postDelayed(new WeakRunnable(txtview),1500); 

just call the main UI thread handler, so if the action is destroyed, the view is null and the current dose is nothing.

also due to a weak relationship, activities can be garbage collected because there is no strong reference to it.

+3
source

I have a doubt if there is no memory leak whenever the device is orientation.

It could be. Within 1.5 seconds. After the queue is empty, the handler can collect garbage, as well as old activity. To be safe, override onPause and call handler.removeCallbacks(null); to clear the handler queue

+3
source

h.postDelayed (new WeakRunnable (txtview), 1500); I think it will be a UI Thread lock. here is a good sample for memory leak. https://github.com/badoo/android-weak-handler

+2
source

Please do this, otherwise you will block UIThread, and this is not recommended. You can also use TimerTask for this, check it out here: http://developer.android.com/reference/java/util/TimerTask.html

 import android.widget.TextView; import android.util.Log; import java.lang.ref.WeakReference; public class HelloWorldActivity extends Activity { private Handler h = new Handler(); private static TextView txtview; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); txtview = (TextView) findViewById(R.id.mainview); h.postDelayed(new Runnable() { @Override public void run() { changeText(); } }, 1500); } public void changeText(){ txtview.setText("Hola mundo."); h.removeCallbacksAndMessages(null); } } 

By the way, you can change the orientation in your emulator as follows: Ctrl + F12

+1
source

All Articles