我是Java的初学者,并创建了一个简单的Java Android代码段,在1.5秒后在Runnable中我将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线程阻塞有关。实际上,此代码在主(UI)线程中运行Handler。为了产生一个新线程,我手动生成一个线程,如下所示:
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给我:update ui from another thread in android我理解为什么应用程序退出了。这一切都归结为你不能从主线程以外的线程调用UI方法的原因。从另一个线程更新UI是不好的做法。
答案 0 :(得分:5)
我怀疑无论何时设备都没有内存泄漏 取向发生。
可能是。持续1.5秒。清空队列后,可以对处理程序进行垃圾回收,也可以使用旧的Activity。要安全覆盖onPause,并调用handler.removeCallbacks(null);
清除处理程序的队列
答案 1 :(得分:3)
如果您使用以下代码,我认为您的代码无泄漏:
private static Handler h = new Handler();
或
txtview.postDelayed(new WeakRunnable(txtview),1500);
因为您已将视图存储为WeakReference。方法:
txtview.postDelayed(new WeakRunnable(txtview),1500);
简单地调用UI线程的主处理程序,因此如果活动被销毁,则视图为null,并且runnable不会产生任何效果。
也因为弱引用,活动可以被垃圾收集,因为没有强烈的引用。
答案 2 :(得分:2)
h.postDelayed(new WeakRunnable(txtview),1500); 我认为这将阻止UI线程。 这是一个很好的内存泄漏示例。 https://github.com/badoo/android-weak-handler
答案 3 :(得分:1)
请执行此操作,否则您将阻止UIThread并且不建议这样做。为此,您还可以使用TimerTask,在此处查看: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);
}
}
顺便说一句,您可以通过以下方式更改模拟器中的方向: Ctrl + F12