有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java这种可运行的内存泄漏安全吗?

我完全是Java初学者,创建了一个简单的Java Android代码段,在运行1.5秒后,我将TextViewHello World更改为Hola Mundo。它工作完美,基本上是一个WeakReference应该防止这种内存泄漏发生,对吗?我怀疑在设备定向时是否绝对没有内存泄漏。我很想检查一下,但无法在我的模拟安卓系统中改变方向

代码如下:

package com.example.helloworld;

import 安卓.app.Activity;
import 安卓.os.Bundle;
import 安卓.os.Handler;
import 安卓.widget.TextView;
import 安卓.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)线程中运行处理程序。要生成一个新线程,我将手动生成一个线程,如下所示:

package com.example.helloworld;

import 安卓.app.Activity;
import 安卓.os.Bundle;
import 安卓.os.Handler;
import 安卓.widget.TextView;
import 安卓.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 give me:update ui from another thread in 安卓我理解了应用程序退出的原因。这一切都归结为除了主线程之外,不能从其他线程调用UI方法的原因从另一个线程更新UI是不好的做法


共 (4) 个答案

  1. # 2 楼答案

    I have a doubt if there's absolutely no memory leak whenever device orientation occurs.

    可能吧。持续1.5秒。队列清空后,可以对处理程序和旧活动进行垃圾收集。为了安全起见,重写onPause,并调用handler.removeCallbacks(null);清除处理程序的队列

  2. # 3 楼答案

    请执行此操作,否则将阻塞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

  3. # 4 楼答案

    我认为,如果您使用:

    private static Handler h = new Handler(); 
    

    或者

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

    因为您已将视图存储为WeakReference。方法:

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

    只需调用UI线程的主处理程序,这样,如果活动被破坏,视图将为null,而可运行线程将为nothing

    此外,由于weakreference,活动可以被垃圾收集,因为它没有强引用