Android Handler:机制、原理与示例

Android Handler:机制、原理与示例

📱 基本示例

  1. 创建与使用主线程 Handler

public class MainActivity extends AppCompatActivity {

private Handler mHandler;

private TextView mTextView;

复制代码
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mTextView = findViewById(R.id.text_view);
    
    // 在主线程创建 Handler
    mHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case 1:
                    mTextView.setText("收到消息:" + msg.obj);
                    break;
            }
        }
    };
    
    // 启动子线程发送消息
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(2000);
                
                Message msg = Message.obtain();
                msg.what = 1;
                msg.obj = "来自子线程的消息";
                mHandler.sendMessage(msg);
                
                // 或使用便捷方式
                mHandler.post(() -> {
                    mTextView.setText("通过 post 更新 UI");
                });
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }).start();
}

}

  1. 创建与使用子线程 Handler

    public class MainActivity extends AppCompatActivity {

    private HandlerThread handlerThread;

    private Handler handler;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    复制代码
     // 创建 HandlerThread
     handlerThread = new HandlerThread("MyHandlerThread");
     handlerThread.start();
     
     // 创建 Handler(关联到 HandlerThread 的 Looper)
     handler = new Handler(handlerThread.getLooper()) {
         @Override
         public void handleMessage(Message msg) {
             // 在子线程执行
             Log.d("Handler", "处理消息: " + msg.what);
         }
     };
     
     // 发送任务
     handler.post(new Runnable() {
         @Override
         public void run() {
             // 在 HandlerThread 中执行
             Log.d("Handler", "执行任务");
         }
     });

    }

    @Override

    protected void onDestroy() {

    super.onDestroy();

    // 退出消息循环

    if (handlerThread != null) {

    handlerThread.quitSafely();

    }

    }

    }

// 创建子线程

new Thread(new Runnable() {

@Override

public void run() {

// 1. 初始化 Looper

Looper.prepare();

复制代码
    // 2. 创建 Handler
    Handler handler = new Handler(Looper.myLooper()) {
        @Override
        public void handleMessage(Message msg) {
            // 处理消息
            Log.d("Handler", "收到消息: " + msg.what);
        }
    };
    
    // 3. 启动消息循环
    Looper.loop();
}

}).start();

  1. 定时任务示例

// 延迟执行

mHandler.postDelayed(() -> {

Log.d("Handler", "3秒后执行");

}, 3000);

// 循环执行

private Runnable mUpdateTask = new Runnable() {

@Override

public void run() {

updateUI();

// 每1秒执行一次

mHandler.postDelayed(this, 1000);

}

};

// 开始循环

mHandler.post(mUpdateTask);

// 停止循环(重要!防止内存泄漏)

@Override

protected void onDestroy() {

super.onDestroy();

mHandler.removeCallbacks(mUpdateTask);

}

说明

.获取looper的方式

Looper.getMainLooper():始终返回主线程的 Looper

Looper.myLooper():获取当前线程的 Looper,可能返回 null

handler.getLooper()

handlerThread.getLooper()

.一个handler对应一个Looper,一个Looper可以对应多个handler

🔧 核心机制

Handler 四件套

┌─────────────────────────────────────────┐

│ MessageQueue(消息队列) │

│ ┌─────────────┬─────────────┐ │

│ │ Message1 │ Message2 │ ... │

│ └─────────────┴─────────────┘ │

└─────────────┬──────────────────────────┘

┌─────────────▼──────────────────────────┐

│ Looper(消息循环器) │

│ • 从 MessageQueue 取出消息 │

│ • 分发给对应的 Handler │

└─────────────┬──────────────────────────┘

┌─────────────▼──────────────────────────┐

│ Handler(消息处理器) │

│ • 发送消息到 MessageQueue │

│ • 处理 Looper 分发的消息 │

└─────────────┬──────────────────────────┘

┌─────────────▼──────────────────────────┐

│ Message(消息) │

│ • what: 消息标识 │

│ • arg1/arg2: 整型参数 │

│ • obj: 对象参数 │

│ • target: 目标 Handler │

└────────────────────────────────────────┘

🧠 工作原理

  1. 消息循环流程

// Looper.loop() 简化逻辑

public static void loop() {

final Looper me = myLooper();

final MessageQueue queue = me.mQueue;

复制代码
for (;;) {
    // 1. 从队列取消息(可能阻塞)
    Message msg = queue.next();
    if (msg == null) return;
    
    // 2. 分发给目标 Handler
    msg.target.dispatchMessage(msg);
    
    // 3. 回收消息到池中
    msg.recycleUnchecked();
}

}

  1. 消息发送与处理

// Handler.sendMessage() 流程

public boolean sendMessage(Message msg) {

return sendMessageDelayed(msg, 0);

}

public boolean sendMessageDelayed(Message msg, long delayMillis) {

// 设置消息的目标 Handler

msg.target = this;

复制代码
// 计算执行时间
if (delayMillis < 0) delayMillis = 0;
long when = SystemClock.uptimeMillis() + delayMillis;

// 入队
return queue.enqueueMessage(msg, when);

}

// 消息分发

public void dispatchMessage(Message msg) {

if (msg.callback != null) {

// 处理 Runnable

handleCallback(msg);

} else {

if (mCallback != null) {

if (mCallback.handleMessage(msg)) return;

}

// 调用 handleMessage()

handleMessage(msg);

}

}

⚙️ 关键技术点

  1. 线程绑定

// 主线程 Looper 初始化(ActivityThread.main())

public static void main(String[] args) {

Looper.prepareMainLooper(); // 创建主线程 Looper

ActivityThread thread = new ActivityThread();

thread.attach(false);

复制代码
if (sMainThreadHandler == null) {
    sMainThreadHandler = thread.getHandler();
}

Looper.loop();  // 开启消息循环
throw new RuntimeException("Main thread loop unexpectedly exited");

}

// 子线程使用 Handler

new Thread(() -> {

// 1. 准备 Looper

Looper.prepare();

复制代码
// 2. 创建 Handler(会自动绑定当前线程的 Looper)
Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        // 处理消息
    }
};

// 3. 开启循环
Looper.loop();

}).start();

  1. 消息池优化

// 消息池避免频繁创建对象

Message msg = Message.obtain(); // 推荐:从池中获取

// vs

Message msg = new Message(); // 不推荐:每次创建新对象

// 使用后系统自动回收

msg.recycleUnchecked();

  1. 同步屏障(Sync Barrier)

// 紧急消息处理

public int postSyncBarrier() {

return mQueue.postSyncBarrier(SystemClock.uptimeMillis());

}

// 异步消息(优先级更高)

msg.setAsynchronous(true);

mHandler.sendMessage(msg);

🚨 注意事项

  1. 内存泄漏处理

// 错误示例:匿名内部类持有 Activity 引用

private Handler mHandler = new Handler() {

@Override

public void handleMessage(Message msg) {

// 持有外部类引用

}

};

// 正确示例1:静态内部类 + 弱引用

private static class SafeHandler extends Handler {

private final WeakReference mActivity;

复制代码
public SafeHandler(Activity activity) {
    mActivity = new WeakReference<>(activity);
}

@Override
public void handleMessage(Message msg) {
    Activity activity = mActivity.get();
    if (activity != null && !activity.isFinishing()) {
        // 安全操作
    }
}

}

// 正确示例2:在 onDestroy 中清理

@Override

protected void onDestroy() {

super.onDestroy();

mHandler.removeCallbacksAndMessages(null);

}

  1. 跨线程通信

// 子线程 → 主线程

new Thread(() -> {

// 耗时操作

String result = doBackgroundWork();

复制代码
// 方式1:sendMessage
Message msg = Message.obtain(mainHandler);
msg.obj = result;
mainHandler.sendMessage(msg);

// 方式2:post(更简洁)
mainHandler.post(() -> updateUI(result));

// 方式3:runOnUiThread(Activity 中)
runOnUiThread(() -> updateUI(result));

}).start();

  1. HandlerThread 使用

// 创建自带 Looper 的工作线程

HandlerThread handlerThread = new HandlerThread("WorkerThread");

handlerThread.start();

// 获取该线程的 Handler

Handler workerHandler = new Handler(handlerThread.getLooper());

// 在工作线程执行任务

workerHandler.post(() -> {

// 在 WorkerThread 中执行

doHeavyWork();

复制代码
// 完成后通知主线程
mainHandler.post(() -> updateUI());

});

// 结束时清理

handlerThread.quitSafely();

📊 性能优化建议

  1. 消息复用:使用 Message.obtain() 而非 new Message()
  2. 及时清理:在合适的生命周期移除回调
  3. 避免过度使用:简单的定时任务可用 postDelayed,复杂调度考虑 RxJava 或 Coroutine
  4. 线程管理:使用 HandlerThread 管理后台线程的 Looper
  5. 同步屏障谨慎用:只在必要时使用异步消息

这种机制使得 Android 能够实现高效、安全的线程间通信,是 Android 异步编程的基石。

相关推荐
哈哈浩丶2 小时前
安卓系统全流程启动
android·linux·驱动开发
summerkissyou19873 小时前
Android-Audio-MediaPlayer-播放-流程
android·audio
mjhcsp4 小时前
C++ 后缀平衡树解析
android·java·c++
没有bug.的程序员5 小时前
Gradle 构建优化深度探秘:从 Java 核心到底层 Android 物理性能压榨实战指南
android·java·开发语言·分布式·缓存·gradle
lljss202011 小时前
MediaPad 10 Link S10-201wa(安卓4.1.2) 安装vlc
android
黄昏晓x11 小时前
C++----异常
android·java·c++
aningxiaoxixi11 小时前
Android Audio 广播之 ACTION_AUDIO_BECOMING_NOISY
android·java·python
Chengbei1113 小时前
内网渗透过程中搜寻指定文件内容Everything小工具
android·安全·网络安全·系统安全·密码学·网络攻击模型·安全架构
coding者在努力13 小时前
LangChain之Prompt核心组件.2026年新版讲解,超详细
android·langchain·prompt