Este Runnable está a salvo de vazamento de memória?
Sou iniciante em Java e criei um snippet Java Android simples, onde, em um Runnable após 1,5 segundos, altero oTextView
deHello World
paraHola Mundo
. Funciona perfeitamente, basicamente umWeakReference
deve impedir que esse vazamento de memória aconteça certo? Tenho uma dúvida se não há absolutamente nenhum vazamento de memória sempre que ocorre a orientação do dispositivo. Gostaria de verificar isso, mas não consigo alterar a orientação no meu Android emulado.
Este é o código:
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);
}
}
}
EDITAR
É seguro contra vazamentos de memória, mas algumas respostas também estavam preocupadas com o bloqueio de threads da interface do usuário. Na verdade, esse código executa o manipulador no segmento principal (UI). Para gerar um novo thread, estou gerando um thread manualmente da seguinte maneira:
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
}
}
}
A questão agora é que parece que não consigo atrasar o segmento gerado de nenhuma maneira, caso contrário ele funciona.
Este:
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
faz com que o aplicativo saia e não entendo o porquê. Algo me diz que estou atrasando o caminho errado.
EDIT2
Graças ao link @EugenMatynov me dê:atualizar a interface do usuário de outro segmento no android Eu entendi por que o aplicativo foi encerrado. Tudo se resume à razãoVocê não pode chamar métodos de interface do usuário de threads diferentes do thread principal. e é uma prática recomendada atualizar a interface do usuário de outro segmento.