`
410063005
  • 浏览: 180002 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

对Android App UI线程的一点理解

 
阅读更多

1. ANR

ANRs (“Application Not Responding”),意思是”应用没有响应“

发生ANR最常见的一种情况: UI线程中执行长时间的任务,如IO或网络操作, 导致UI线程5秒内没有响应输入事件

 

参考 http://blog.csdn.net/leilu2008/article/details/6689405

 

2. 如何避免ANR

防止UI线程中执行长时间的任务,避免UI线程阻塞。 以Activity为例,我们应该避免在Activity的生命周期方法中执行耗时操作。

3. 问题

Android系统创建UI线程时,同时在这个线程中启动了一个消息循环(Looper), Looper.loop()源码注释指出该方法可能阻塞。 这里的loop()显然是在UI线程中执行,不会阻塞UI线程吗?为什么没有引起ANR?

 

ActivityThread.java

 

    public static final void main(String[] args) {
        ...
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        ...
        Looper.loop();
        ...
   }

 

Looper.java

 

    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) {
            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);
                
                // 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);
                }
                
                msg.recycle();
            }
        }
    }

 

4. Looper不会阻塞UI线程

Looper不会阻塞UI线程。 原因是,UI线程消息循环开始后, UI线程内发生的所有操作(以Activity为例,比如Activity的生命周期的管理)都是通过这个消息循环来完成。即,Activity的生命回调方法(onCreate, onResume)最终都会以一种间接的方式由这个消息循环来调用。 

 

参考  http://stackoverflow.com/questions/6984263/android-looper-and-call-stack 

http://stackoverflow.com/questions/5193913/handlers-messagequeue-looper-do-they-all-run-on-the-ui-thread

 

5. 分析

 

Activity启动时相关的几个类

 

注意图中的ActivityManagerProxy和ActivityManagerService,后者为服务端, 前者可以看作它的远程代理。 ActivityThread通过这个代理进行IPC调用。另外, ActivityThread的一个类型为ApplicationThread(可以看出, 它间接地继承自Binder, 并且是ActivityThread的内部类)成员变量作为远程调用的参数被传递给了ActivityManagerService, 这里的ApplicationThread是ActivityManagerService能够调用Activity的回调方法的关键。

 

Activity启动的时序图

 

由上图可以看出,一系列调用过程最终结果是一个相应Message进入MessageQueue, 由ActivityThread的一个Handler成员变量进行消息的处理。其处理流程基本可归纳为


handleXXXActivity() ----> performXXXActivity()---->Instrument.callActivityOnXXX()--->Activity.onXXX()


这里的Activit.onXXX()就是我们编写的Activity生命周期方法。

 

所以说Activity的生命周期方法是通过UI线程的消息循环来完成, 并不存在Looper阻塞UI线程的问题。我们需要注意的就是避免在这些回调方法中执行耗时操作。

 

  • 大小: 50 KB
  • 大小: 70 KB
0
0
分享到:
评论

相关推荐

    Xamarin.Android 非UI线程更新UI

    总结起来,Xamarin.Android的非UI线程更新UI涉及了对Android线程模型的理解以及各种线程间通信技术的运用。通过Handler、RunOnUiThread、AsyncTask等方法,我们可以确保UI操作始终在主线程中安全执行。遵循最佳实践...

    android 多线程 下载 更新 ui 例子

    本示例"android 多线程 下载 更新 ui 例子"旨在教你如何在Android环境中使用多线程进行文件下载,并实时更新UI来显示下载进度。 在Android主线程中,我们不能执行长时间运行的任务,因为这会导致应用程序无响应...

    Android app 闪退弹框 CrashUI当 Android app内发生exception

    在Android中,如果主线程(UI线程)抛出未处理的异常,应用会立即停止运行,显示一个白色的空白屏幕或“应用已停止”的系统弹窗。为了避免这种情况,开发者通常会在应用启动时或者全局级别设置一个...

    android主线程、子线程及线程间通信方式测试app

    本文将深入探讨Android主线程(也称为UI线程)、子线程以及它们之间的通信方式,结合"android主线程、子线程及线程间通信方式测试app"的描述,我们将详细分析相关知识点。 1. **Android主线程**:主线程是应用程序...

    Android 多线程下载+UI进度条刷新

    在Android系统中,主线程(UI线程)主要负责处理用户界面交互,而后台任务如网络请求、数据处理等通常不应在主线程中执行,因为这会阻塞UI更新,导致应用无响应(ANR)。因此,我们需要使用子线程(也称工作线程)来...

    AndroidApp中使用SurfaceView制作多线程动画的实例讲解.docx

    在Android开发中,为了确保应用的流畅性和响应性,通常需要将耗时操作(如网络请求)放在非UI线程中进行。然而,由于安全性考虑,在非UI线程中直接修改UI组件(如调用`onDraw`方法)是被禁止的。这时,如果需要在...

    Android源码——UI界面源码.zip

    8. **异步更新UI**:由于Android的UI线程不能长时间阻塞,所以涉及耗时的操作(如网络请求)应放在后台线程执行。通过Handler、AsyncTask或LiveData等工具,可以安全地在后台线程完成工作并更新UI。 9. **可访问性...

    Android UI组件实例集合

    是一个工具包用来帮助设计和开发 Android 用户界面,包含三个单独的工具:Android Asset Studio用户界面原型模具,Android 设计预览,时常需要重复确认程序版面设计状况的 Android App 开发者,应该会爱上这个轻量级...

    Android多线程断点下载-IT计算机-毕业设计.zip

    因此,Android引入了多线程,让耗时任务在后台线程运行,保持UI线程的流畅。可以使用`Thread`、`Runnable`、`AsyncTask`或者更现代的`ExecutorService`来实现后台线程。 断点下载的核心在于记录已下载的数据状态。...

    基于Android的看小说APP源码Android本科毕业设计Android小说阅读器、小说APP源码

    5. **异步处理**:Android提倡使用异步操作处理耗时任务,防止UI线程阻塞。可以使用AsyncTask、Handler/Looper机制或现代的RxJava、Kotlin协程来实现。 6. **阅读器功能**:阅读界面可能包含字体大小调整、背景颜色...

    oschina android app 2.2.1 源码收藏

    本文将针对"OSChina android app 2.2.1"的源码进行深度分析,旨在揭示其中的技术栈、设计模式以及优化策略,帮助开发者更好地理解和运用Android应用开发。 首先,源码的分析始于项目结构。在"libraries"目录下,...

    android app连接蓝牙打印机打印

    以上就是基于`PrintDemo`项目中可能涉及的关键技术点,这些知识点可以帮助你理解如何在Android App中实现蓝牙打印机的连接和打印功能。在实际开发中,你可以根据`PrintDemo`的源代码深入学习和实践,以完善和优化你...

    酒店Android APP 项目

    【酒店Android APP 项目】是一个综合性的开发案例,主要涵盖了Android平台上的应用开发技术,包括UI设计、数据存储以及项目构建等方面。在这个项目中,开发者使用了Android Studio作为集成开发环境,通过XML来构建...

    Android 线程开发 开发实例

    我们的主线程(UI线程)就是一个消息循环的线程。针对这种消息循环的机制,我们引入一个新的机制Handle,我们有消息循环,就要往消息循环里 面发送相应的消息,自定义消息一般都会有自己对应的处理,消息的发送和...

    Android APP启动多图滚动的UI引导页动画效果.rar

    Android APP 引导页动画效果,这个相信大家都熟悉,是软件入口的闪屏界面,安卓手机APP启动时多图滚动或者手指滑动切换的UI引导页动画效果,本实例引导页使用的pageview适配器,图片的下半部分有几个小圆点,显示...

    蓝牙遥控小车Android APP

    这可能涉及到多线程编程,以防止UI线程阻塞。 8. **测试与调试**:在开发过程中,测试是必不可少的环节。开发者需要在不同设备上测试APP的兼容性和稳定性,同时使用Logcat等工具进行调试,查找并修复潜在问题。 总...

    AndroidApp.rar

    注意,由于蓝牙通信的异步性质,你需要在单独的线程中处理读写操作,以免阻塞UI线程。同时,为了保证数据的完整性和可靠性,可能需要添加错误检测和重传机制。 5. **AT指令读写**: 在AT模式下,你可以向HC-05发送...

    android网络测速app源代码

    总的来说,开发这样一个Android网络测速App涵盖了Android应用开发的多个方面,包括网络编程、数据库操作、文件处理、地理位置服务、UI设计、权限管理、多线程、数据可视化以及异常处理等,对于Android开发者来说是一...

    Androidapp接入PaddleOCR资源

    3. **异步处理**: 避免在UI线程中执行耗时的OCR操作,采用异步方式处理,提高用户体验。 以上是Android应用接入PaddleOCR资源的基本流程和关键知识点。实际开发中,可能还需要根据应用需求进行定制,如优化图像处理...

Global site tag (gtag.js) - Google Analytics