首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Android 防止按鈕重複點擊與 Handler 內存洩漏解決方案

     編輯:Java 相關知識

問題一:按鈕快速重複點擊導致重複提交

現象

用戶在網絡請求未返回時連續點擊提交按鈕,觸發多次 submitOrder(),產生重複訂單。

解決方案:自定義 NoDoubleClickListener

public abstract class NoDoubleClickListener implements View.OnClickListener {
    public static final int MIN_CLICK_DELAY_TIME = 1000; // 1秒
    private long lastClickTime = 0;

    @Override
    public final void onClick(View v) {
        long currentTime = System.currentTimeMillis();
        if (currentTime - lastClickTime > MIN_CLICK_DELAY_TIME) {
            lastClickTime = currentTime;
            onNoDoubleClick(v);
        }
    }
    public abstract void onNoDoubleClick(View v);
}

使用方式

submitButton.setOnClickListener(new NoDoubleClickListener() {
    @Override
    public void onNoDoubleClick(View v) {
        submitOrder(); // 業務邏輯
    }
});

優勢:零侵入業務代碼,僅替換監聽器與回調方法名,邏輯清晰優雅。


問題二:Handler 導致 Activity 內存洩漏

洩漏原因

// 錯誤示例
public class SampleActivity extends Activity {
    private Handler handler = new Handler() { // 匿名內部類持有外部類引用
        @Override
        public void handleMessage(Message msg) { ... }
    };
    private Runnable runnable = new Runnable() { // 同理
        @Override public void run() { ... }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        handler.postDelayed(runnable, 1000 * 60 * 10); // 10分鐘後執行
        finish(); // Activity 銷毀,但 MessageQueue 持有 handler/runnable 引用,導致無法 GC
    }
}

正確修復:靜態內部類 + 弱引用

public class SampleActivity extends Activity {
    private static class MyHandler extends Handler {
        private final WeakReference activityRef;
        public MyHandler(SampleActivity activity) {
            activityRef = new WeakReference<>(activity);
        }
        @Override
        public void handleMessage(Message msg) {
            SampleActivity activity = activityRef.get();
            if (activity != null) {
                // 安全訪問 activity
            }
        }
    }

    private static final Runnable sRunnable = new Runnable() { // 靜態匿名類不持有外部引用
        @Override public void run() { /* ... */ }
    };

    private final MyHandler handler = new MyHandler(this);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        handler.postDelayed(sRunnable, 1000 * 60 * 10);
        finish(); // 此時 Activity 可正常 GC
    }
}

關鍵點總結

  1. Handler/Runnable 定義為 static 內部類或獨立類,斷開對外部類的隱式引用。
  2. 需訪問 Activity 時,通過 WeakReference 持有,並在使用前檢查 get() != null。
  3. postDelayed 的 Runnable 也必須是靜態的,否則同樣洩漏。
  4. 在 onDestroy() 中調用 handler.removeCallbacksAndMessages(null) 進一步保障。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved