鹤壁做网站哪家便宜,深圳招聘网站排行,代理公司注册机构,深圳 网站设计在Android中#xff0c;线程内部或者线程之间进行信息交互时经常会使用消息#xff0c;这些基础的东西如果我们熟悉其内部的原理#xff0c;将会使我们容易、更好地架构系统#xff0c;避免一些低级的错误。在学习Android中消息机制之前#xff0c;我们先了解与消息有关的…在Android中线程内部或者线程之间进行信息交互时经常会使用消息这些基础的东西如果我们熟悉其内部的原理将会使我们容易、更好地架构系统避免一些低级的错误。在学习Android中消息机制之前我们先了解与消息有关的几个类1.Message消息对象顾名思义就是记录消息信息的类。这个类有几个比较重要的字段a.arg1和arg2我们可以使用两个字段用来存放我们需要传递的整型值在Service中我们可以用来存放Service的ID。b.obj该字段是Object类型我们可以让该字段传递某个多项到消息的接受者中。c.what这个字段可以说是消息的标志在消息处理中我们可以根据这个字段的不同的值进行不同的处理类似于我们在处理Button事件时通过switch(v.getId())判断是点击了哪个按钮。在使用Message时我们可以通过new Message()创建一个Message实例但是Android更推荐我们通过Message.obtain()或者Handler.obtainMessage()获取Message对象。这并不一定是直接创建一个新的实例而是先从消息池中看有没有可用的Message实例存在则直接取出并返回这个实例。反之如果消息池中没有可用的Message实例则根据给定的参数new一个新Message对象。通过分析源码可得知Android系统默认情况下在消息池中实例化10个Message对象。2.MessageQueue消息队列用来存放Message对象的数据结构按照“先进先出”的原则存放消息。存放并非实际意义的保存而是将Message对象以链表的方式串联起来的。MessageQueue对象不需要我们自己创建而是有Looper对象对其进行管理一个线程最多只可以拥有一个MessageQueue。我们可以通过Looper.myQueue()获取当前线程中的MessageQueue。3.LooperMessageQueue的管理者在一个线程中如果存在Looper对象则必定存在MessageQueue对象并且只存在一个Looper对象和一个MessageQueue对象。在Android系统中除了主线程有默认的Looper对象其它线程默认是没有Looper对象。如果想让我们新创建的线程拥有Looper对象时我们首先应调用Looper.prepare()方法然后再调用Looper.loop()方法。典型的用法如下class LooperThread extends Thread{public Handler mHandler;public void run(){Looper.prepare();//其它需要处理的操作Looper.loop();}}倘若我们的线程中存在Looper对象则我们可以通过Looper.myLooper()获取此外我们还可以通过Looper.getMainLooper()获取当前应用系统中主线程的Looper对象。在这个地方有一点需要注意假如Looper对象位于应用程序主线程中则Looper.myLooper()和Looper.getMainLooper()获取的是同一个对象。4.Handler消息的处理者。通过Handler对象我们可以封装Message对象然后通过sendMessage(msg)把Message对象添加到MessageQueue中当MessageQueue循环到该Message时就会调用该Message对象对应的handler对象的handleMessage()方法对其进行处理。由于是在handleMessage()方法中处理消息因此我们应该编写一个类继承自Handler然后在handleMessage()处理我们需要的操作。下面我们通过跟踪代码分析在Android中是如何处理消息。首先贴上测试代码/**** author coolszy**/public class MessageService extends Service{private static final String TAG MessageService;private static final int KUKA 0;private Looper looper;private ServiceHandler handler;/*** 由于处理消息是在Handler的handleMessage()方法中因此我们需要自己编写类* 继承自Handler类然后在handleMessage()中编写我们所需要的功能代码* author coolszy**/private final class ServiceHandler extends Handler{public ServiceHandler(Looper looper){super(looper);}Overridepublic void handleMessage(Message msg){// 根据what字段判断是哪个消息switch (msg.what){case KUKA://获取msg的obj字段。我们可在此编写我们所需要的功能代码Log.i(TAG, The obj field of msg: msg.obj);break;// other casesdefault:break;}// 如果我们Service已完成任务则停止ServicestopSelf(msg.arg1);}}Overridepublic void onCreate(){Log.i(TAG, MessageService--onCreate());// 默认情况下Service是运行在主线程中而服务一般又十分耗费时间如果// 放在主线程中将会影响程序与用户的交互因此把Service// 放在一个单独的线程中执行HandlerThread thread new HandlerThread(MessageDemoThread, Process.THREAD_PRIORITY_BACKGROUND);thread.start();// 获取当前线程中的looper对象looper thread.getLooper();//创建Handler对象把looper传递过来使得handler、//looper和messageQueue三者建立联系handler new ServiceHandler(looper);}Overridepublic int onStartCommand(Intent intent, int flags, int startId){Log.i(TAG, MessageService--onStartCommand());//从消息池中获取一个Message实例Message msg handler.obtainMessage();// arg1保存线程的ID在handleMessage()方法中// 我们可以通过stopSelf(startId)方法停止服务msg.arg1 startId;// msg的标志msg.what KUKA;// 在这里我创建一个date对象赋值给obj字段// 在实际中我们可以通过obj传递我们需要处理的对象Date date new Date();msg.obj date;// 把msg添加到MessageQueue中handler.sendMessage(msg);return START_STICKY;}Overridepublic void onDestroy(){Log.i(TAG, MessageService--onDestroy());}Overridepublic IBinder onBind(Intent intent){return null;}}运行结果注在测试代码中我们使用了HandlerThread类该类是Thread的子类该类运行时将会创建looper对象使用该类省去了我们自己编写Thread子类并且创建Looper的麻烦。下面我们分析下程序的运行过程1.onCreate()首先启动服务时将会调用onCreate()方法在该方法中我们new了一个HandlerThread对象提供了线程的名字和优先级。紧接着我们调用了start()方法执行该方法将会调用HandlerThread对象的run()方法public void run() {mTid Process.myTid();Looper.prepare();synchronized (this) {mLooper Looper.myLooper();notifyAll();}Process.setThreadPriority(mPriority);onLooperPrepared();Looper.loop();mTid -1;}在run()方法中系统给线程添加的Looper同时调用了Looper的loop()方法public static final void loop() {Looper me myLooper();MessageQueue queue me.mQueue;while (true) {Message msg queue.next(); // might block//if (!me.mRun) {// break;//}if (msg ! null) {if (msg.target null) {// No target is a magic identifier for the quit message.return;}if (me.mLogging! null) me.mLogging.println( Dispatching to msg.target msg.callback : msg.what);msg.target.dispatchMessage(msg);if (me.mLogging! null) me.mLogging.println( Finished to msg.target msg.callback);msg.recycle();}}}通过源码我们可以看到loop()方法是个死循环将会不停的从MessageQueue对象中获取Message对象如果MessageQueue 对象中不存在Message对象则结束本次循环然后继续循环如果存在Message对象则执行 msg.target.dispatchMessage(msg)但是这个msg的.target字段的值是什么呢我们先暂时停止跟踪源码返回到onCreate()方法中。线程执行完start()方法后我们可以获取线程的Looper对象然后new一个ServiceHandler对象我们把Looper对象传到ServiceHandler构造函数中将使handler、looper和messageQueue三者建立联系。2.onStartCommand()执行完onStart()方法后将执行onStartCommand()方法。首先我们从消息池中获取一个Message实例然后给Message对象的arg1、what、obj三个字段赋值。紧接着调用sendMessage(msg)方法我们跟踪源代码该方法将会调用sendMessageDelayed(msg, 0)方法而sendMessageDelayed()方法又会调用sendMessageAtTime(msg, SystemClock.uptimeMillis() delayMillis)方法在该方法中我们要注意该句代码msg.target thismsg的target指向了this而this就是ServiceHandler对象因此msg的target字段指向了ServiceHandler对象同时该方法又调用MessageQueue 的enqueueMessage(msg, uptimeMillis)方法final boolean enqueueMessage(Message msg, long when) {if (msg.when ! 0) {throw new AndroidRuntimeException(msg This message is already in use.);}if (msg.target null !mQuitAllowed) {throw new RuntimeException(Main thread not allowed to quit);}synchronized (this) {if (mQuiting) {RuntimeException e new RuntimeException(msg.target sending message to a Handler on a dead thread);Log.w(MessageQueue, e.getMessage(), e);return false;} else if (msg.target null) {mQuiting true;}msg.when when;//Log.d(MessageQueue, Enqueing: msg);Message p mMessages;if (p null || when 0 || when p.when) {msg.next p;mMessages msg;this.notify();} else {Message prev null;while (p ! null p.when when) {prev p;p p.next;}msg.next prev.next;prev.next msg;this.notify();}}return true;}该方法主要的任务就是把Message对象的添加到MessageQueue中(数据结构最基础的东西自己画图理解下)。handler.sendMessage()--handler.sendMessageDelayed()--handler.sendMessageAtTime()--msg.target this;queue.enqueueMessage把msg添加到消息队列中3.handleMessage(msg)onStartCommand()执行完毕后我们的Service中的方法就执行完毕了那么handleMessage()是怎么调用的呢在前面分析的loop()方法中我们当时不知道msg的target字段代码什么通过上面分析现在我们知道它代表ServiceHandler对象msg.target.dispatchMessage(msg);则表示执行ServiceHandler对象中的dispatchMessage()方法public void dispatchMessage(Message msg) {if (msg.callback ! null) {handleCallback(msg);} else {if (mCallback ! null) {if (mCallback.handleMessage(msg)) {return;}}handleMessage(msg);}}该方法首先判断callback是否为空我们跟踪的过程中未见给其赋值因此callback字段为空所以最终将会执行handleMessage()方法也就是我们ServiceHandler类中复写的方法。在该方法将根据what字段的值判断执行哪段代码。至此我们看到一个Message经由Handler的发送MessageQueue的入队Looper的抽取又再一次地回到Handler的怀抱中。而绕的这一圈也正好帮助我们将同步操作变成了异步操作。以上就是本文的全部内容希望对大家的学习有所帮助也希望大家多多支持脚本之家。