我是
Java的初学者,已经创建了一个简单的Java
Android代码片段,在1.5秒后我在Runnable中将TextView从Hello World更改为Hola Mundo.它完美无缺,基本上WeakReference应该防止这种内存泄漏发生吗?我怀疑是否在设备方向发生时绝对没有内存泄漏.我很想检查这个,但无法在我模拟的Android中改变方向.
@H_403_2@这是代码:
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); } } }@H_403_2@编辑 @H_403_2@内存泄漏是安全的,但是一些答案也与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 } } }@H_403_2@现在的问题是我似乎无法以任何方式延迟产生的线程,否则它的工作原理. @H_403_2@这个:
try { Thread.sleep(1500); } catch (InterruptedException e) { e.printStackTrace(); }@H_403_2@使应用程序自行退出,我不明白为什么.有些东西告诉我,我是以错误的方式推迟它. @H_403_2@EDIT2 @H_403_2@感谢链接@EugenMatynov给我:update ui from another thread in android我理解为什么应用程序退出了.这一切都归结为您无法从主线程以外的线程调用UI方法的原因.从另一个线程更新UI是不好的做法.
解决方法
我认为如果您使用以下代码是无泄漏的:
private static Handler h = new Handler();@H_403_2@要么
txtview.postDelayed(new WeakRunnable(txtview),1500);@H_403_2@因为您已将视图存储为WeakReference.方法:
txtview.postDelayed(new WeakRunnable(txtview),1500);@H_403_2@简单地调用UI线程的主处理程序,因此如果活动被销毁,则视图为null,并且runnable不会产生任何影响. @H_403_2@同样由于弱引用,活动可以被垃圾收集,因为没有强烈的参考.