簡體   English   中英

使用 android 處理程序時,如何解決有關 memory 泄漏的警告?

[英]How can I resolve warnings about memory leaks when using android Handler?

我是學習android的初學者。 我在學習 Thread 時使用了 Handler。 順便說一句,我在 android studio 中使用 Handler 警告 memory 泄漏。 我搜索了很多不同的問題,但沒有與我的案例相對應的部分。 使用處理程序時,如何解決有關 memory 泄漏的警告?

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 object 的引用。 當您在Thread中保留對任何View的強引用時,您不僅存儲了View object,而且還存儲了一個Context object 代表創建它的Activity 現在由於Thread不與 Activity 生命周期綁定,即使在Activity被銷毀后它們也會繼續運行。 如果是這種情況, Thread將通過該View object 保存已破壞的Activity引用,從而創建 memory 泄漏。

上述問題可以通過存儲View object 的弱引用來解決,以便 GC 可以在必要時對其進行垃圾回收。 通過以下方式,您可以擺脫 memory 泄漏:

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;
            }
        }
    }
}

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

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM