Это Runnable безопасно от утечки памяти?
Я абсолютный новичок в Java и создал простой фрагмент Java для Android, в котором в Runnable через 1,5 секунды я изменяюTextView
отHello World
вHola Mundo
, Работает без нареканий, в основномWeakReference
должно предотвратить эту утечку памяти, правильно? У меня есть сомнения, если нет абсолютно никакой утечки памяти, когда происходит ориентация устройства. Я хотел бы проверить это, но не могу изменить ориентацию в моем эмулируемом Android.
Это код:
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);
}
}
}
РЕДАКТИРОВАТЬ
Это безопасно от утечек памяти, но несколько ответов были также связаны с блокировкой потока пользовательского интерфейса. Фактически этот код запускает обработчик в основном потоке (UI). Чтобы создать новый поток, я создаю поток вручную следующим образом:
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
}
}
}
Проблема в том, что я не могу задержать порожденную нить, иначе она работает.
Это:
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
заставляет приложение выйти само, а я не понимаю почему. Что-то говорит мне, что я задерживаю это неправильно.
EDIT2
Благодаря ссылке @EugenMatynov дайте мне:обновить пользовательский интерфейс из другой темы в Android Я понял, почему приложение вышло. Все сводится к причинеВы не можете вызывать методы пользовательского интерфейса из потоков, отличных от основного потока. и это плохая практика, чтобы обновить пользовательский интерфейс из другого потока.