异步消息机制

1.  一个线程里面只有一个Looper。

2. 子线程也可创建handler。

前后需分别加上Looper.prepare();和Looper.loop();

标准写法:

Looper.prepare();

Handler mHandler = new Handler() {

@Override

publicvoidhandleMessage(Message msg) {

if (msg.what == 10000) {

Log.i(TAG,"在子线程中定义Handler,并接收到消息。。。");

}

}};

Looper.loop();

prepare 中创建looper。

3. 主线程对应的方法在ActivityThread的main方法中。

4. Looper的构造方法中初始化了一个MessageQueue对象

privateLooper(boolean quitAllowed) {

mQueue = new MessageQueue(quitAllowed);

mThread = Thread.currentThread();

}

总:Looper.prepare()方法初始话了一个Looper对象并关联在一个MessageQueue对象,并且一个线程中只有一个Looper对象,只有一个MessageQueue对象。而Handler的构造方法则在Handler内部维护了当前线程的Looper对象

5. handler.sendMessage(msg) 会调用queue.enqueueMessage(msg, uptimeMillis);,会发现 MessageQueue并没有使用列表将所有的Message保存起来,而是使用Message.next保存下一个Message,从而按照时间将所有的Message排序;

6. Looper.loop()

可以看到Looper.loop()方法里起了一个死循环,不断的判断MessageQueue中的消息是否为空,如果为空则直接return掉,然后执行queue.next()方法

可以看到其大概的实现逻辑就是Message的出栈操作,里面可能对线程,并发控制做了一些限制等。获取到栈顶的Message对象之后开始执行:

msg.target.dispatchMessage(msg);

Handle的dispatchMessage()

/**  

* Handle system messages here. */

publicvoiddispatchMessage(Message msg) {

if (msg.callback != null) {

handleCallback(msg);

}else {

if (mCallback != null) {

if (mCallback.handleMessage(msg)) {

return;

}

 }

handleMessage(msg);

}

}

可以看到,如果我们设置了callback(Runnable对象)的话,则会直接调用handleCallback方法:

privatestaticvoidhandleCallback(Message message) {

message.callback.run();

}

msg.callback为空的话,会直接调用我们的mCallback.handleMessage(msg),即handler的handlerMessage方法。由于Handler对象是在主线程中创建的,所以handler的handlerMessage方法的执行也会在主线程中


原作者的总结:

1)主线程中定义Handler,直接执行:

Handler mHandler =new Handler() {

@Override

publicvoidhandleMessage(Message msg) {

super.handleMessage(msg);

}};

而如果想要在子线程中定义Handler,则标准的写法为:

// 初始化该线程Looper,MessageQueue,执行且只能执行一次

Looper.prepare();

// 初始化Handler对象,内部关联Looper对象

Handler mHandler =new Handler() {

@Override

publicvoidhandleMessage(Message msg) {

super.handleMessage(msg);

}

};

// 启动消息队列出栈死循环

Looper.loop();

2)一个线程中只存在一个Looper对象,只存在一个MessageQueue对象,可以存在N个Handler对象,Handler对象内部关联了本线程中唯一的Looper对象,Looper对象内部关联着唯一的一个MessageQueue对象。

3)MessageQueue消息队列不是通过列表保存消息(Message)列表的,而是通过Message对象的next属性关联下一个Message从而实现列表的功能,同时所有的消息都是按时间排序的。

4)android中两个子线程相互交互同样可以通过Handler的异步消息机制实现,可以在线程a中定义Handler对象,而在线程b中获取handler的引用并调用sendMessage方法。

5)activity内部默认存在一个handler的成员变量,android中一些其他的异步消息机制的实现方法: 
Handler的post方法:

mHandler.post(new Runnable() {

@Override

publicvoidrun() {

}

});

查看其内部实现:

publicfinalbooleanpost(Runnable r) {

return sendMessageDelayed(getPostMessage(r), 0);

}

可以发现其内部调用就是sendMessage系列方法。。。

view的post方法:

publicbooleanpost(Runnable action) {

final AttachInfo attachInfo = mAttachInfo;

if (attachInfo != null) {

return attachInfo.mHandler.post(action);

}

// Assume that post will succeed later

ViewRootImpl.getRunQueue().post(action);

returntrue;

}

可以发现其调用的就是activity中默认保存的handler对象的post方法。

activity的runOnUiThread方法:

publicfinalvoidrunOnUiThread(Runnable action) {

if (Thread.currentThread() != mUiThread) {

mHandler.post(action);

}else {

action.run();

}

}

判断当前线程是否是UI线程,如果不是,则调用handler的post方法,否则直接执行run方法。

http://blog.csdn.net/qq_23547831/article/details/50751687


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用Java实现的一个简单倒计时时钟,使用了子线程和Swing框架的异步消息机制实现计时和更新UI界面。 ```java import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class CountdownTimer implements ActionListener { private JFrame frame; private JLabel countdownLabel; private JTextField inputField; private JButton startButton; private JButton stopButton; private int countdownTime; private boolean isRunning; private Thread timerThread; public CountdownTimer() { frame = new JFrame("Countdown Timer"); frame.setSize(400, 300); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new FlowLayout()); JLabel inputLabel = new JLabel("Enter countdown time:"); inputLabel.setFont(new Font("Arial", Font.PLAIN, 18)); frame.add(inputLabel); inputField = new JTextField(10); inputField.setFont(new Font("Arial", Font.PLAIN, 18)); frame.add(inputField); startButton = new JButton("Start"); startButton.setFont(new Font("Arial", Font.PLAIN, 18)); startButton.addActionListener(this); frame.add(startButton); stopButton = new JButton("Stop"); stopButton.setFont(new Font("Arial", Font.PLAIN, 18)); stopButton.addActionListener(this); stopButton.setEnabled(false); frame.add(stopButton); countdownLabel = new JLabel("0"); countdownLabel.setFont(new Font("Arial", Font.PLAIN, 36)); countdownLabel.setPreferredSize(new Dimension(300, 100)); frame.add(countdownLabel); frame.setVisible(true); } public void actionPerformed(ActionEvent e) { if (e.getSource() == startButton) { if (!isRunning) { try { countdownTime = Integer.parseInt(inputField.getText()); } catch (NumberFormatException ex) { countdownTime = 0; } if (countdownTime > 0) { isRunning = true; timerThread = new Thread(new CountdownTask()); timerThread.start(); startButton.setEnabled(false); stopButton.setEnabled(true); } } } else if (e.getSource() == stopButton) { if (isRunning) { isRunning = false; try { timerThread.join(); } catch (InterruptedException ex) { ex.printStackTrace(); } countdownTime = 0; countdownLabel.setText("0"); startButton.setEnabled(true); stopButton.setEnabled(false); } } } private class CountdownTask implements Runnable { public void run() { while (countdownTime > 0 && isRunning) { SwingUtilities.invokeLater(new UpdateLabelTask(countdownTime)); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } countdownTime--; } isRunning = false; startButton.setEnabled(true); stopButton.setEnabled(false); } } private class UpdateLabelTask implements Runnable { private int time; public UpdateLabelTask(int time) { this.time = time; } public void run() { countdownLabel.setText(String.valueOf(time)); } } public static void main(String[] args) { new CountdownTimer(); } } ``` 在这个例子中,我们使用了Swing框架创建了一个GUI界面,包括一个输入框、两个按钮和一个文本标签。当用户输入需要倒计时的时间后,点击开始按钮,就会创建一个子线程,使用while循环进行倒计时,并通过SwingUtilities的invokeLater方法实现异步消息机制更新文本标签上的数字。当用户点击停止按钮时,程序会结束子线程并重置倒计时时间。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值