• 7.1 基础知识Android消息处理机制


    1. Android消息处理机制: Handler, MessageQueue, Looper, Thread

    线程概念 : 一个应用程序运行时它的主体被称为进程,
    一个进程内部可以有多个线程,
    线程共享进程的资源 
    线程间通信

    在android系统中是怎么封装通讯的,假如存在两个线程A和B,如果A线程要告诉B线程一些消息,怎么实现?

    A进程怎么发发消息?(1)构造消息,消息里面有数据信息和处理函数(2)发消息;这两个步骤在android源码中被封装成Handler

    消息在android中被封装为Message,A发送Message给B,可能B处理不过来,因此A把消息放到B进程里面的消息队列MessageQueue类,在B进程的循环体中做什么事?

    (1)、从队列中取出消息;(2)处理消息,执行消息的处理函数;这两个步骤在android源码中被封装成Looper

    Looper源码在frameworks/base/core/java/android/os/Looper.java

    Handler源码在frameworks/base/core/java/android/os/Handler.java   //ctrl+shift+n在输入handler.java来打开

    a. 创建MessageQueue: Looper.prepare()
    b. 使用Handler构造、发送Message
    b.1 new Handler  //创建handler的时候可以指定Looper即消息接受者和Callback回调函数即消息的处理函数,如果不知道肯定有默认的Looper和消息处理函数
    b.2 Handler.sendMessage, sendEmptyMessageAtTime, sendMessageDelayed

    c. 使用Looper循环处理消息:在loop函数中有个for死循环
    c.1 从MessageQueue中取出Message,//Message msg = queue.next();
    c.2 执行它的处理函数: msg.target.dispatchMessage(msg)//target就是Handler,dispatchMessage会调用处理函数

      

    应用程序编写:

    功能说明:app中创建一个button,创建子线程,添加消息处理功能,并且给Button添加处理函数,并且主线程会监测button,当button按下时给子线程发送消息,子线程收到消息后打印出来

    import android.view.View;

    import android.util.Log;//打印导入的库

    public class MainActivity extends AppCompatActivity{

      private Button mButton;

      private final String TAG = "MessageTest";

      private int ButtonCount = 0;

      private Thread myThread;

      private MyThread myThread2;

      private Handler mHandler;

      private int mMessageCount = 0;

      class MyRunnable:implements Runable{

        int count=0;

        public void run(){

          for(;;){

            Log.d(TAG,"MyThread"+(count++));

            try{  

              Thread.sleep(3000);

            }catch(INterrupteException e){

              e.printStackTrace();

            }

          }

        }

      }

      class Mythread extends Thread{       //android只带的消息处理是在HandlerThread.java中,其功能同我们怎么的Mythread,如果不自己创建Mythread,可以直接使用HandlerThread类

        public void run(){

          super.run();

          Looper.prepare();//创建消息队列

          Looper.loop();//从消息队列中取出消息,调用消息的处理函数

        }

        public Looper getLooper(){

          return Looper.myLooper(); 

        }

      }

      pretected void onCreate(Bundle savedInstanceState){

        ........

        ........

        mButton = (Button)findViewById(R.id.button);//双击Button,按下shift+F1,可以查看类的帮助文档

        mButton.setOnClickListener(new View.OnClickListener(){

          public void onClick(View v){

            Log.d(TAG,"SendMessage"+(ButtonCount++) );

            Message msg = new Message();

            mHandler.sendMessage(msg );//发送消息的会从把消息放到消息队列中,消息队列是从handler创建的时候从Looper中获得

          }

        });

        myThread = new Thread(new MyRunnable,"MessageTestThread");//(runnable接口的方法run是线程的主体函数)

        myThread.start();

        myThread2 = new MyThread();

        myThread2 .start();//功能和myThread一样,start会导致MyThread的run函数被执行,run函数会执行Looper.prepare()去创建消息队列,但这个函数并不一定马上就执行,如果住进程中创建Handler的时候没有队列,会存在风险,所以修改class MyThread extends Thread{}

        ////我们现在的代码里面有三个线程了,主线程、myThread和myThread2,,要确定消息发给谁Looper

        mHandler = new Handler(myThread2.getLooper(),new Handler.Callback(){

          public boolean handleMessage(Message msg){

            Log.d(TAG,"getMessage"+(mMessageCount++))

            return false;

          }

        });

      }

    }

    针对上面所说的风险修改class MyThread extends Thread{},如下:

    class MyThread extends Thread{

      private Looper mLooper;

        public void run(){

          super.run();

          Looper.prepare();//创建消息队列

          mLooper = Looper.myLooper();

          notifyAll();//当主线程调用getLooper,在mLooper 为空的时候会休眠,所以这里需要唤醒休眠的线程

          Looper.loop();//从消息队列中取出消息,调用消息的处理函数

        }

        public Looper getLooper(){

          if(!isAlive()){

            return null;

          }

          synchronized(this){

            while(isAlive() && mLooper == null){

              try{

                wait();

              }catch (InterruptedException e){

              }

            }

          }

          return mLooper;

        }

    }

    修改代码使用系统只带的消息处理线程:

    1、导入包:import android.os.HandlerThread;

    2、在public class MainActivity extends AppCompatActivity中新增

      private HandlerThread myThread3;

      private Handler mHandler3;

      myThread3 = new HandlerThread("MessageTestThread3");

      myThread3 .start();

      mHandler3 = new Handler(myThread3.getLooper());

      在button的onClick函数中添加:

      mHandler3.post(new Runnable(){

        public void run(){

          Log.d(TAG,"getMessage for Thread3"+(mMessageCount++));

        }

      });

      

  • 相关阅读:
    设计模式 享元模式(池化技术)
    设计模式 混合模式(整体部分模式)
    设计模式 适配器模式
    Flex3示例、 安装 、注册码
    VS2010错误
    转载:glut.h 与 stdlib.h中 的exit()重定义问题的解决
    宿迁软件QQ群(109233721)
    百度地图 开发API接口啦
    Sublime Text 插件个人使用总结&推荐
    sublime text2 使用安装插件中文乱码问题解决
  • 原文地址:https://www.cnblogs.com/liusiluandzhangkun/p/9127501.html
Copyright © 2020-2023  润新知