`
willsunforjava
  • 浏览: 167884 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Android异步消息处理

 
阅读更多

最近看了《Android内核剖析》这本书,将学习笔记整理如下

1. 异步消息线程

异步消息线程不同一般线程的是,它的线程run方法有一个无限循环,没循环一次,从其内部的消息队列中取出一个消息并调用回调函数进行处理。如果消息队列为空,线程暂停,直到消息队列中有新的消息。

 

一般而言有两种需求需要用到异步线程处理:

(1) 任务需要常驻

(2) 任务需要根据外部传递的消息做出不同的操作

 

2. Android异步线程的实现方法

 

在线程的内部有一个或多个Handler对象,外部程序通过该handler对象向线程发送异步消息,消息经由Handler传递到MessageQueue对象中。线程内部只能包含一个MessageQueue对象,线程主执行函数从MessageQueue中读取消息,并回调Handler对象中的回调函数handleMessage()。下面的代码是一个简单的实例。

 

 

  class LooperThread extends Thread {
      public Handler mHandler;
      
      public void run() {
          Looper.prepare();
          
          mHandler = new Handler() {
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };
          
          Looper.loop();
      }
  }

 

2.1 Looper

Looper的作用有两点,第一是调用静态函数prepare()为线程创建一个消息队列;第二是调用静态函数loop(),使调用该函数的线程进行无限循环,并从消息队列中读取消息。

(1)调用prepare()函数

 

    public static final void prepare() {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper());
    }

   //Looper构造函数  

 

  private Looper() {
        mQueue = new MessageQueue();
        mRun = true;
        mThread = Thread.currentThread();
    }

 在代码中,变量sThreadLocal的类型是ThreadLocal,该类的作用是提供“线程局部存储”,从变量的作用域来理解下这个概念。

 

函数成员变量-------------------------------- 仅在函数内部有效
类成员变量 --------------------------------- 仅在对象内部有效
线程局部存储(TLS)变量-------------------- 在本线程内的任何对象内保持一致
类静态变量------------------------------------ 在本进程内的任何对象内保持一致
跨进程通信(IPC)变量----------------------- 一般使用Binder进行定义,在所有进程中保持一致

 

 

 

 

 

 

 

 

从上述的代码可以看到,一个线程只允许创建一个Looper对象,这是因为每个Looper对象都会创建一个MessageQueue对象,一个异步线程中只能有一个消息队列,所以也就只能有一个Looper对象

(2)调用loop()函数

 

public static final void loop() {
        Looper me = myLooper();
        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();
        
        while (true) {
            // might block 如果队列为空,则当前线程就会被挂起,next()函数内部会暂停线程
            Message msg = queue.next();
            
            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的类型是Handler,msg最终交予handleMessage()处理
                msg.target.dispatchMessage(msg);
                if (me.mLogging!= null) me.mLogging.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("Looper", "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);
                }
                //回收message对象占用的系统资源
                msg.recycle();
            }
        }
    }
   

 

2.2 MessageQueue

消息队列采用排队方式对消息进行处理,即先到的消息会先得到处理,但如果消息本身指定了被处理的时刻,则必须等到该时刻才能处理该消息。

 

2.3 Handler

尽管MessageQueue提供了直接读/写的函数接口,但对于应用程序员而言,一般不直接读/写消息队列。

程序员一般使用Handler类向消息队列发送消息,并重载Handler的handleMessage函数添加消息处理代码。

handler对象只能添加到有消息队列的线程中,否则会发生异常。因此,在构造Handler对象前,必须已经执行过Looper.prepare(),但prepare()不能被执行两次。

一个线程中可以包含多个Handler对象。在Looper.loop函数中,不同的Message对应不同的Handler对象,从而回调不同的handleMessage函数。

异步消息处理线程处理用于多线程的消息传递外,它还和跨进程调用(IPC)一起被使用,用于实现异步跨进程调用。

 

 

 

 

 

 


 

  • 大小: 6.9 KB
  • 大小: 7.4 KB
分享到:
评论

相关推荐

    Android异步消息处理机制详解及源码分析 - 工匠若水 - 博客频道 - CSDN1

    【Android异步消息处理机制详解及源码分析】 在Android应用开发中,为了保证用户界面的流畅性,我们需要避免在主线程(UI线程)执行耗时操作。Android提供了异步消息处理机制,由Handler、Message、MessageQueue和...

    Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系 - Hongyang -

    【Android异步消息处理机制】深入理解Looper、Handler、Message三者关系 在Android系统中,异步消息处理机制是实现线程间通信和保证UI线程安全的关键组件。它涉及到了三个核心类:Looper、Handler和Message。这篇...

    Android异步消息处理机制实现原理详解

    在Android系统中,异步消息处理机制是一种关键的多线程通信方式,它涉及到四个主要对象:Looper、Handler、Message和MessageQueue。这些组件协同工作,确保在不同线程之间安全、高效地传递数据和执行任务。下面我们...

    android中异步消息处理

    ### Android中异步消息处理...Looper负责创建消息循环并在循环中处理消息,MessageQueue用于存储消息,而Handler则作为消息的发送者和接收者。掌握这些基本概念对于理解和解决Android应用程序中的多线程问题至关重要。

    Android多线程及异步任务消息处理机制 一 Handler的使用

    本篇博文将聚焦于Android中的`Handler`机制,它是Android异步消息处理的核心组件。通过`Handler`,我们可以实现UI线程与工作线程之间的通信,确保UI的流畅更新。 `Handler`的主要作用是在Android的消息队列中发送和...

    异步消息处理线程

    在Android开发中,异步消息处理是一种常见的多线程编程技术,主要用于解决UI线程(主线程)与后台任务之间的通信问题。标题“异步消息处理线程”着重强调了这种处理方式,它允许开发者在不阻塞主线程的情况下执行...

    Android代码-Android 一些重要知识点解析整理

    Android 异步消息处理机制完全解析,带你从源码角度彻底理解 Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系 Android消息循环分析 Android Activity developer 官网 (强烈推荐 ...

    Android编程实现异步消息处理机制的几种方法总结

    本文实例讲述了Android编程实现异步消息处理机制的几种方法。分享给大家供大家参考,具体如下: 1、概述 Android需要更新ui的话就必须在ui线程上进行操作。否则就会抛异常。 假如有耗时操作,比如:在子线程中下载...

    Android消息处理机制

    Handler主要用于发送和处理消息,它是Android异步消息处理的核心类。当我们在主线程中创建一个Handler对象时,它会自动与当前线程的Looper关联。通过调用Handler的`sendMessage()`或`post()`方法,我们可以将Message...

    Android异步加载文字

    总之,“Android异步加载文字”项目涵盖了Android应用开发中的基本异步处理技巧,通过学习和实践,开发者可以掌握如何在后台加载数据并安全地更新UI,提高应用的性能和用户体验。同时,这也是Android应用开发进阶...

    Android异步加载图片例子

    在这个"Android异步加载图片例子"中,我们将探讨如何在Android应用中实现这一功能。 首先,我们需要理解Android的主线程(UI线程)与工作线程的区别。主线程负责处理用户界面交互,而工作线程则用于执行耗时操作,...

    android 异步显示View

    AsyncTask是一种轻量级的异步处理类,适用于执行一次性任务,如网络请求或数据库操作。它包含三个泛型参数,分别代表后台任务的输入类型、进度类型和输出类型。通过`doInBackground()`方法执行后台任务,然后在`...

    全面总结Android中线程的异步处理方式

    Handler 、 Looper 、Message 这三者都与Android异步消息处理线程相关的概念。那么什么叫异步消息处理线程呢? 异步消息处理线程启动后会进入一个无限的循环体之中,每循环一次,从其内部的消息队列中取出一个消息,...

    android异步消息机制 源码层面彻底解析(1)

    `Handler`的主要功能是发送和处理消息,`sendMessage()`方法用于发送消息,`handleMessage()`方法用于处理消息。 2. **Message**: Message是数据载体,用于在Handler和Looper之间传递信息。`Message.obtain()`...

    android 异步操作框架

    **Android异步操作的重要性** 在Android系统中,主线程负责处理UI更新和用户交互,如果在此线程执行耗时操作,会导致应用无响应(ANR:Application Not Responding),严重影响用户体验。因此,开发者需要将网络请求...

    Android异步请求网络图片demo

    通过学习和实践这个"Android异步请求网络图片demo",开发者可以掌握如何在Android应用中实现高效、流畅的网络图片加载,同时理解异步处理、内存管理、网络请求库等关键概念,这对于构建高质量的Android应用至关重要...

    android异步加载图片缓存释放

    总结,"android异步加载图片缓存释放"涉及到的关键技术包括异步处理、内存缓存、磁盘缓存、图片库的使用以及性能优化。理解和掌握这些知识点,可以有效地提升Android应用在处理图片加载时的效率和用户体验。

    网络图片实现 Android异步加载处理.zip

    网络图片实现 Android异步加载处理

    Android异步操作数据库

    因此,"Android异步操作数据库"是一个至关重要的知识点,它涉及到如何在后台线程中安全、高效地处理数据库事务,避免阻塞UI。 1. **AsyncTask** Android提供了一个内置的异步任务类`AsyncTask`,适用于短时间的...

Global site tag (gtag.js) - Google Analytics