我是学习android的初学者。 我在学习线程时正在使用处理程序。 顺便说一下,我使用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();
            }
        });
    }
}

#1楼 票数:0 已采纳

基本上, TextView或任何其他View持有代表相应ActivityContext对象的引用。 当您在Thread引用任何View ,不仅要存储View对象,还要存储表示创建它的ActivityContext对象。 现在,由于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;
            }
        }
    }
}

#2楼 票数:0

Roaim,Mark Keen在他们的帮助下,我解决了这个问题,并给出了完整的答案。 感谢Roaim,Mark Keen。

public class HandlerActivity extends AppCompatActivity implements Runnable {

ProgressBar pb;
TextView txtRate;
Button btnStart;
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();
        }
    });
}

private static class WeakHandler extends Handler {
    private final WeakReference<HandlerActivity> mWeakActivity;

    private WeakHandler(HandlerActivity AppCompatActivity) {
        mWeakActivity = new WeakReference<>(AppCompatActivity);
    }

    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        HandlerActivity _activity = mWeakActivity.get();

        if (_activity != null) {

            switch (msg.what) {
                case 0:
                    _activity.pb.setProgress(_activity.value);
                    _activity.txtRate.setText("Process : " + _activity.value + "%");
                    break;
            }
        }
    }
}

private final WeakHandler mHandler = new WeakHandler(this);

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

        mHandler.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();
        }
    });
}

}

  ask by Glacier.Nick translate from so

未解决问题?本站智能推荐:

2回复

Android处理程序,内存泄漏?

我了解Handler可能会泄漏Android中的内存,但是我不太确定自己所做的操作是否正确: 另外,如果我只想使用Handler来“发布”,“ postDelayed”,“ removeCallbacks”,那么我不关心handleMessage,只是创建一个新的Handler实例来做到
1回复

处理程序未收到消息

我正在尝试在后台线程中做一些工作,然后转到下一个活动。 工作完成后,我会通知主线程,但处理程序永远不会收到此通知。 这是代码: 另外,我想知道此代码是否存在内存泄漏?
3回复

这段代码可以避免 Android 处理程序内存泄漏吗?

handler1是一个泄漏。 我想将handler1代码转换为handler2代码。 这可以吗? 这两个代码有什么区别? public class MainActivity extends AppCompatActivity { @Override protected voi
2回复

Android - mainThread处理程序会导致内存泄漏吗?

我很好奇为什么下面是内存泄漏,因为mHandler是在mainThread上创建的,现在当onDestroy被调用时它不会直接杀死线程? 在销毁活动后,处理程序如何存在? 我还没有新的主题。 我是否理解一个处理程序,如果它有消息队列的东西,即使在一个线程被销毁后仍然存在? 参考文档即
2回复

方法内的处理程序会泄漏内存吗?

我知道在类中声明的处理程序可能会泄漏内存,因为它包含对其外部类的引用。 在这种情况下,我们应该使用带有弱引用的静态嵌套类。 但是如果在方法中声明了处理程序,该怎么办? 我遇到了以下情况,并不确定它是否正确实施。 有人可以解释或给我一个提示吗? 我甚至不知道应该搜索什么。
1回复

Android:通过处理程序发送大量消息时显然存在内存泄漏

我有一个应用程序,其中一个线程试图通过Handler将大量Location对象发送到UI线程,在那里它们被分析并传递给其他线程。 我注意到该应用程序有内存泄漏,因为它最终在启动后2-3小时崩溃。 如果我使用DDMS来分析堆,我注意到“数据对象”的数量逐渐增加(每分钟大约1500)。 似乎那
1回复

Android中用于kotlin的静态等价物,以避免处理程序内存泄漏

当我在使用java之前在Android中使用处理程序时,我会得到一条Android Studio lint消息,说我应该使用静态处理程序,否则会发生内存泄漏。 由于Kotlin没有静态关键字,我该如何处理呢? 这是我的班级: 为了避免使用Kotlin泄漏内存,我需要做些什么特别的事情
1回复

Handler中的Android内存泄漏

此功能使用计数值更新自定义进度,以便在10秒内开始,在0处停止,并且每毫秒将进度更新为流畅的。 (请注意,“ updateProgress”调用了invalidate()函数) 如果我使用正常的进度,那没关系,我没有内存泄漏,但是如果我使用此代码,则“ Android探查器”检查器中的内