android - 使用 android Handler 时如何解决有关内存泄漏的警告?

标签 android multithreading memory-leaks handler

我是学习android的初学者。 我在学习 Thread 时使用的是 Handler。 顺便说一句,我使用 Handler 来警告 android studio 中的内存泄漏。 我搜索了很多不同的问题,但没有与我的情况相对应的部分。 如何解决使用处理程序时有关内存泄漏的警告?

public class HandlerActivity extends AppCompatActivity implements Runnable {

    ProgressBar pb;
    TextView txtRate;
    Button btnStart;
    static int value;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.progress);

        pb = findViewById(R.id.pb);
        txtRate = findViewById(R.id.txtRate);
        btnStart = findViewById(R.id.btnStart);

        btnStart.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Thread th = new Thread(HandlerActivity.this);
                th.start();
            }
        });
    }

        Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            pb.setProgress(value);
            txtRate.setText("Process : " + value + "%");
        }
    };

    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            value = i;

            handler.sendEmptyMessage(0);

            try {
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(HandlerActivity.this, "Progress Done !", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

最佳答案

基本上 TextView 或任何其他 View 持有代表相应 ActivityContext 对象的引用。当您在 Thread 中保持对任何 View 的强引用时,您不仅存储了 View 对象,还存储了一个 Context 对象表示创建它的 Activity。现在,由于 Thread 与 Activity 生命周期无关,即使在 Activity 被销毁后,它们仍将继续运行。如果是这种情况,Thread 将通过该 View 对象持有一个被破坏的 Activity 的引用,从而造成内存泄漏。

上述问题可以通过存储View 对象的弱引用来解决,这样GC 就可以在必要时对其进行垃圾回收。您可以通过以下方式消除内存泄漏:

public class HandlerActivity extends AppCompatActivity implements Runnable {
    WeakReference<ProgressBar> pb;
    WeakReference<TextView> txtRate;
    Button btnStart;
    static int value;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        pb = new WeakReference<>(findViewById(R.id.pb)); // you may require to cast findViewById() to ProgressBar
        txtRate = new WeakReference<>(findViewById(R.id.txtRate));  // you may require to cast findViewById() to TextView
        ...
    }

    Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if(pb.get()!=null) pb.get().setProgress(value);
            if(txtRate.get()!=null) txtRate.get().setText("Process : " + value + "%");
        }
    };

    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            // Its always recommended to check if activity is running and stop the thread if not running
            if(isFinishing() || isDestroyed()) {
                return;
            }
        }
    }
}

关于android - 使用 android Handler 时如何解决有关内存泄漏的警告?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58000065/

相关文章:

java - 如何将文件保存在下载目录中?

c# - 为什么空白线程要占用 30% 的 CPU?

c++ - 阻塞和非阻塞队列

multithreading - 如果我可以调高程序的优先级,为什么我必须为一项处理任务使用多个线程?

Android - Google Maps API V2,避免内存泄漏

android - 打开 HPROF 文件时出错 : IOException: Unknown HPROF Version

android - 在 USB 主机模式下安装的 USB 存储设备上的文件 I/O(Android 3.1 及更高版本)

java - 单击监听器不会切换 Activity

android - 在自定义 ListView 中获取 View

javascript - 如果 dom 元素有指向闭包的指针,如果我从页面中删除 dom 元素,这会导致内存泄漏吗?