zoukankan      html  css  js  c++  java
  • Android笔记(三十四) Android中线程之间的通信(六)Handle中的post()方法详解

             我们之前都是使用sendMessage()方法来发送消息,使用handleMessage来处理消息的,今天我们来看另外一种方法,先看代码:

    package cn.lixyz.handlertest;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.os.Handler;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    
    
    public class MainActivity extends Activity {
    
        private Button button;
        private Handler handler = new Handler();
        private TextView textView;
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            textView = (TextView) findViewById(R.id.textView);
            button = (Button) findViewById(R.id.button);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    TestThread t = new TestThread();
                    t.start();
                }
            });
    
        }
    
        class TestThread extends Thread {
            @Override
            public void run() {
                super.run();
                Runnable r = new Runnable() {
                    @Override
                    public void run() {
                        for (int i = 0; i < 5; i++) {
                            Log.d("TTTT", (i + 1) + " 秒");
                            try {
                                Thread.sleep(1000 * 1);
                                textView.setText("5秒后修改的内容");
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
    
                        }
                    }
                };
    
                handler.post(r);
            }
        }
    
    }
    MainActivity.java
    <LinearLayout 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"
        android:orientation="vertical"
        tools:context=".MainActivity">
    
        <TextView
            android:id="@+id/textView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:gravity="center"
            android:text="更改前"
            android:textSize="30sp" />
    
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="30dp"
            android:text="Send Message" />
    
    
    </LinearLayout>
    acitivit_main.xml

             点击按钮,运行结果:

             从代码中我们可以看到,我新建了一个线程,线程中创建了一个Runnable对象,这个Runnable对象中有修改UI的操作,然后使用调用了Handler的 post() 方法,那么我们就来看一下这个 post() 究竟是如何实现的。

             查看Handler的源代码,找到post()方法

        public final boolean post(Runnable r)
        {
           return  sendMessageDelayed(getPostMessage(r), 0);
        }

             我们发现,其实post方法直接调用了一个延时发送消息的方法 sendMessageDelayed() ,只不过延时为0,继续找到 getPostMessage() 方法

        private static Message getPostMessage(Runnable r) {
            Message m = Message.obtain();
            m.callback = r;
            return m;
        }

             在上面的代码中,我们发现,getPostMessage方法内新获取了一个Message对象,并且将我们传入的Runnage对象赋值给了这个Message对对象的 callback 属性,然后将之返回

             所以说, post() 方法的本质就是将一个Runnable对象赋值给一个Message属性的 callback 属性,然后将这个Message对象放入到消息队列当中去

             而之前我们说过,Looper的 loop() 方法会循环的从消息队列中取出消息,那么这时候Looper是怎么工作的呢,找到Looper的 loop() 方法

        public static void loop() {
            final Looper me = myLooper();
            if (me == null) {
                throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
            }
            final MessageQueue queue = me.mQueue;
    
            // Make sure the identity of this thread is that of the local process,
            // and keep track of what that identity token actually is.
            Binder.clearCallingIdentity();
            final long ident = Binder.clearCallingIdentity();
    
            for (;;) {
                Message msg = queue.next(); // might block
                if (msg == null) {
                    // No message indicates that the message queue is quitting.
                    return;
                }
    
                // This must be in a local variable, in case a UI event sets the logger
                Printer logging = me.mLogging;
                if (logging != null) {
                    logging.println(">>>>> Dispatching to " + msg.target + " " +
                            msg.callback + ": " + msg.what);
                }
    
                msg.target.dispatchMessage(msg);
    
                if (logging != null) {
                    logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
                }
    
                // Make sure that during the course of dispatching the
                // identity of the thread wasn't corrupted.
                final long newIdent = Binder.clearCallingIdentity();
                if (ident != newIdent) {
                    Log.wtf(TAG, "Thread identity changed from 0x"
                            + Long.toHexString(ident) + " to 0x"
                            + Long.toHexString(newIdent) + " while dispatching to "
                            + msg.target.getClass().getName() + " "
                            + msg.callback + " what=" + msg.what);
                }
    
                msg.recycle();
            }
        }

              和之前说的一样,loop()方法执行之后,同样的先拿到Looper对象,之后开始循环从消息队列中取出消息,执行到 msg.target.dispatchMessage(msg); 因为Message的 target 属性是 Handler 类型的,我们去看Handler的 despatchMessage 方法

        public void dispatchMessage(Message msg) {
            if (msg.callback != null) {
                handleCallback(msg);
            } else {
                if (mCallback != null) {
                    if (mCallback.handleMessage(msg)) {
                        return;
                    }
                }
                handleMessage(msg);
            }
        }

              可见,先进对收取到的Message对象的 callback 属性进行判断,如果不为空,为调用 handleCallback 方法,查看 handleCallback 方法

        private static void handleCallback(Message message) {
            message.callback.run();
        }

                message.callback.run(); 直接调用了Runnable对象的 run() 方法,而不是创建一个新线程,然后再调用这个线程的start方法。

     

  • 相关阅读:
    数据库的三大范式
    mysql中变量的定义
    java实现用两个栈实现队列
    java实现替换空格
    java实现二维数组中查找
    struts2核心配置之Action
    struts2核心配置之struts.xml
    初识struts2
    $.ajax()参数详解
    百度Map-JSAPI-覆盖物范围查询标记
  • 原文地址:https://www.cnblogs.com/xs104/p/4822783.html
Copyright © 2011-2022 走看看