Handler详解系列(五)——Handler的post()方法详解

简介: MainActivity如下: package cc.testui1;import android.os.Bundle;import android.

MainActivity如下:

package cc.testui1;

import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.app.Activity;
/**
 * Demo描述:
 * 在子线程中更改UI的方式一
 * 
 * 在子线程中利用主线程的Handler的post()方法
 * 更改UI这个在子线程中sendMessage()原理和形式都很类似.
 * 
 * 详细分析:
 * 在Handler调用其post()方法时,方法的调用顺序如下:
 * Handler的post()方法--->Handler的sendMessageDelayed()方法--->
 * Handler的sendMessageAtTime()方法.
 * 至此又回到了前面熟悉的sendMessageAtTime()
 * 
 * 详细的代码如下:
 * public final boolean post(Runnable r){
 *    return  sendMessageDelayed(getPostMessage(r), 0);
 * }
 * 
 * 
 * private final Message getPostMessage(Runnable r) {
 *    Message m = Message.obtain();
 *    m.callback = r;
 *    return m;
 * }
 * 
 * 
 * public final boolean sendMessageDelayed(Message msg, long delayMillis){
 *   if (delayMillis < 0) {
 *       delayMillis = 0;
 *      }
 *   return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
 * }
 * 
 * 
 * 在这个详细的过程中可以看到在post(Runnable r)中利用该方法的输入参数r调用了getPostMessage(r)
 * 将r封装成了一个Message.
 * 重点是getPostMessage(r)方法中的 m.callback = r
 * 将r赋值给了Message的callback!!!!!
 * 
 * 回顾一下出队时调用的dispatchMessage()方法
 * 下面接着看Handler的dispatchMessage(Message msg)方法:
 *  public void dispatchMessage(Message msg) {
 *       //1 message的callback
 *    if (msg.callback != null) {
 *       handleCallback(msg);
 *    } else {
 *       //2 handler的callback
 *       if (mCallback != null) {
 *           if (mCallback.handleMessage(msg)) {
 *               return;
 *          }
 *      }
 *      //3 Handler的handleMessage()
 *      handleMessage(msg);
 *    }
 *  }
 * 
 * 
 * 在1处就判断出该Message的callback不为null,于是调用 handleCallback(msg);
 * 详细代码如下:
 * private static void handleCallback(Message message) {
 *   message.callback.run();
 * }
 * 该方法比较简单:就是直接调用post(Runnable r)的输入参数(Runnable对象)的run()方法.
 * 
 * 小结:
 * 1 在子线程中利用post(Runnable r)更新UI,原理和sendMessage()类似.
 * 2 注意:
 *   在下面的示例中mHandler是主线程的Handler.
 *   所以“在子线程中利用post(Runnable r)更新UI”这个说法不是特别准确.
 *   确切地说还是在子线程中发送了消息到主线程的消息队列从而更新了UI.
 * 3 调用post(Runnable r)不会开启一个新的线程,UI的更新是在主线程中完成的!!!!!!!!!!!!!!
 *   在下面的示例中可在两个地方输出线程ID发现两个值是一样的.
 *   所以在post方法中勿做耗时操作!!!!!!!!!!!!!!!!!!!!!!!
 * 4 其实在第一次看到“message.callback.run().....调用post(Runnable r)不会开启一个新的线程,UI更新是在主线程中完成的....”
 *   时,脑子里发热有点晕:既然都调用run()方法了,还不会开启线程???
 *   哎,这是平常看多了线程Thread和它里面的run()方法带来的误解.
 *   当然Thread调用start()是会开启一个线程的,这个毋庸置疑.
 *   但是如下:
 *   Runnable runnable=new Runnable() {
 *       @Override
 *       public void run() {
 *             System.out.println("Runnable中线程ID:"+Thread.currentThread().getId());
 *            }
 *   };
 *   runnable.run();
 *   它会在一个新线程中运行么?当然不会,直观地说就是它还没有和Thread任何关系.
 *   这么写的话此处的runnable只是一个Runnable接口实现类的对象而已,且该对象调用了方法run().
 *   此时就和一个普通的Object类对象object调用method没啥区别了.
 *   
 * 
 * 
 * 参考资料:
 * 1 http://www.jb51.net/article/37465.htm
 * 2 http://www.eoeandroid.com/blog-660972-48541.html
 * 3 https://software.intel.com/zh-cn/blogs/2010/09/15/start-run
 *   Thank you very much
 *
 */
public class MainActivity extends Activity {
    private TextView mTextView;
    private Handler mHandler;
    private Button mButton;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		init();
	}
    private void init(){
    	mHandler=new Handler();
    	mTextView=(TextView) findViewById(R.id.textView);
    	mButton=(Button) findViewById(R.id.button);
    	mButton.setOnClickListener(new OnClickListenerImpl());
    	System.out.println("UI线程ID="+Thread.currentThread().getId());
    }
    
  
    private class OnClickListenerImpl implements OnClickListener{
		@Override
		public void onClick(View v) {
			new Thread(){
	    		public void run() {
	    			mHandler.post(new Runnable() {
						@Override
						public void run() {
							System.out.println("post(Runnable r)里的run()方法中线程ID="+Thread.currentThread().getId());
							mTextView.setText("My number is 007");
						}
					});
	    		};
	    	}.start();
			
		}
    	
    }
	
}




main.xml如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
   >

     <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="test"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="50dip"
        />
     
     <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="120dip"
        />
    
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="测试在子线程中更新UI" 
        android:layout_centerInParent="true"
        />

</RelativeLayout>


相关文章
|
7月前
|
消息中间件 存储
Handler
Handler
67 1
|
7月前
|
消息中间件 存储 安全
handler
handler
66 0
|
存储 API
10JavaWeb基础 - Request类
10JavaWeb基础 - Request类
69 0
|
程序员 C++
set_new_handler(0)是什么意思?有什么用?
set_new_handler(0)是什么意思?有什么用?
102 0
|
缓存 Java Shell
Handler 的 Message 实例怎么获得?为什么不是直接 new?
Handler 的 Message 实例怎么获得?为什么不是直接 new?
|
JSON 数据格式
09准备将Handler的返回值写入ServletResponse
在RequestMappingHandlerAdapter初始化完成后设置默认的HandlerMethodReturnValueHandler HandlerMethodReturnValueHandler体系介绍 HandlerMethodReturnValueHandler的执行流程
208 0
|
消息中间件 存储 Java
你真的了解Handler吗
今天发一个以前的文章,关于Handler的全面解析,大家看看吧~「周末愉快」!
219 0
你真的了解Handler吗
|
消息中间件 Android开发
【Android 异步操作】手写 Handler ( Handler 发送与处理消息 | Handler 初始化 | 完整 Handler 代码 )
【Android 异步操作】手写 Handler ( Handler 发送与处理消息 | Handler 初始化 | 完整 Handler 代码 )
155 0
|
消息中间件 Android开发 程序员
浅谈Handler
前言 积土成山,风雨兴焉;积水成渊,蛟龙生焉;积善成德,而神明自得; Handler消息传递机制 出于性能优化考虑,Android的UI操作并不是线程安全的,这意义着如果有多个线程并发操作UI组件,则可能导致线程安全问题。
1412 0