View绘制流程源码解析-第一篇

Android应用层View绘制流程与源码分析,墙都不扶就服你 通过上面分析可以看出measure过程主要就是从顶层父View向子View递归调用view.measure方法(measure中又回调onMeasure方法)的过程。 阅读详情

绘制流程概览

Android程序启动 -> Activity加载并调用生命周期onCreate -> Activity调用setContentView -> UI绘制

Android启动流程分析

我们都知道Android程序的启动入口是ActivityThread.main函数,那么看一看main函数是如何进行启动的。

ActivityThread.class

public static void main(String[] args) {
   …
    ActivityThread thread = new ActivityThread();
    thread.attach(false);
    …
}
private void attach(boolean system) {
  	…
        final IActivityManager mgr = ActivityManager.getService();
        try {
            mgr.attachApplication(mAppThread);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
	…
}

由上面的源码可知,我们在main函数中做了两件事情:

  • 生成一个ActivityThread对象
  • 调用该对象的attach方法

在attach方法中,也做了两件事情:

  • 获取了IActivityManager的对象实例
  • 执行该对象的attachApplication方法

通过ActivityManager.getService()获取到Activity管理器接口对象,那么如何拿到的呢?我们来看下源码实现:

ActivityManager.class

/**
 * @hide
 */
public static IActivityManager getService() {
    return IActivityManagerSingleton.get();
}

private static final Singleton<IActivityManager> IActivityManagerSingleton =
        new Singleton<IActivityManager>() {
            @Override
            protected IActivityManager create() {
                final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                final IActivityManager am = IActivityManager.Stub.asInterface(b);
                return am;
            }
        };

  • 服务管理器通过getService拿到了ActivityService 的IBinder对象,通过跨进程获取到am对象。
  • mgr.attachApplication(mAppThread)是将ApplicationThread和ActivityManagertService相关联。

在APP进程启动之后,AMS便会跨binder调用到ApplicationThread的scheduleLaunchActivity,启动Activity。
详细的介绍请参照深入理解Activity——Token之旅

通过上面的分析,我们知道ApplicationThread这个对象在启动过程中起着至关重要的作用,来看下它的源码:
ApplicationThread类里面都干了什么事情?

ApplicationThread.class

private class ApplicationThread extends IApplicationThread.Stub {
  public final void schedulePauseActivity(IBinder token, boolean finished, ...
  public final void scheduleStopActivity(IBinder token, boolean showWindow, ...
   @Override public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ...
...

如上图所示,一堆的schedule方法,按照字面翻译,我们可以猜测出,这个是在Activity状态变化时去调用的方法。
在诸多的schedule方法里面,根据注释得知,scheduleLaunchActivity是在Activity加载的时候调用,我们来看一下:

ApplicationThread.class

        // we use token to identify this activity without having to send the
        // activity itself back to the activity manager. (matters more with ipc)
        @Override
        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
                CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
                int procState, Bundle state, PersistableBundle persistentState,
                List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
                boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {

            updateProcessState(procState, false);

            ActivityClientRecord r = new ActivityClientRecord();

         ...
            updatePendingConfiguration(curConfig);

            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

根据代码我们可以分析

  • 创建了ActivityClientRecord对象
  • 将ActivityClientRecord对象以及标志位LAUNCH_ACTIVITY发送出去

ApplicationThread.class

private void sendMessage(int what, Object obj) {
        sendMessage(what, obj, 0, 0, false);
    }
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }

final H mH = new H();

private class H extends Handler {
...
}

通过以上代码可以知道,将创建的ActivityClientRecord对象以及标志位通过handler发送出去,那我们顺着找到mH的handleMessage方法

private class H extends Handler {
...
public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                  ...
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
                  ...
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                   ...
                } break;
                   ...
            }
          ...
        }
 private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
  ...
             Activity a = performLaunchActivity(r, customIntent);
  ...
}

 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
  ...
             if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
             } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
             }
  ...
}

对应着LAUNCH_ACTIVITY,调用到了handleLaunchActivity函数-> performLaunchActivity函数,在performLaunchActivity函数中,我们可以看到 mInstrumentation.callActivityOnCreate的字样,猜的没错的话,这就是调用Activity的onCreate函数的入口了,我们看下源码:

Instrumentation.class

 /**
     * Perform calling of an activity's {@link Activity#onCreate}
     * method.  The default implementation simply calls through to that method.
     *  @param activity The activity being created.
     * @param icicle The previously frozen state (or null) to pass through to
     * @param persistentState The previously persisted state (or null)
     */
    public void callActivityOnCreate(Activity activity, Bundle icicle,
            PersistableBundle persistentState) {
        prePerformCreate(activity);
        activity.performCreate(icicle, persistentState);
        postPerformCreate(activity);
    }

Activity.class

  final void performCreate(Bundle icicle) {
        performCreate(icicle, null);
    }

    final void performCreate(Bundle icicle, PersistableBundle persistentState) {
      ...
        if (persistentState != null) {
            onCreate(icicle, persistentState);
        } else {
            onCreate(icicle);
        }
      ...
    }
public void onCreate(@Nullable Bundle savedInstanceState,
            @Nullable PersistableBundle persistentState) {
        onCreate(savedInstanceState);
    }

总结一下调用关系,Instrumentation. callActivityOnCreate-> Activity. performCreate->Activity.onCreate。
到此为止,我们的整个APP已经成功启动啦~
总结一下:
APP启动到调用Activity.create函数调用总结.png

2.Activity调用setContentView做了什么?
敬请期待

Activity 启动流程至view绘制到屏幕显示 Activity 启动 至 view绘制 至 屏幕显示 实际效果:Activity冷启动的时候会闪黑屏,就是A启动B,这个过程中会闪黑屏,虽然网上说可以设置一个闪屏页,中间有个过渡效果,或者设置B为透明主题,这样在启动的时候就看不到黑屏了。只是感觉启动B的这个过程漫长而已,又比如说你从桌面启动A,你把A设为透明,你就会感觉你点击A之后半天没反应没启动起来,实际是有反应的哇,因为你设置的透明,所以... 阅读详情

相关推荐

Android View绘制及事件(三)自定义View及View绘制流程

前言 一、自定义View介绍 二、View绘制流程 2.1Measure() 2.2 Layout() 2.2 Draw() 注意 前言 我们经常使用TextView、button等控件,但是有些同学对于它们是如何显示和扩展的却并不那么熟悉。而这一块的知识也进阶高手必备的,写这一篇文章是想把view绘制这块的技术全面总结一下。 Activity作为应用程序的载体负责向用...

csdn_aiyang的博客 2266

View绘制流程分析

想要弄清楚View是怎么绘制的得先弄明白View是怎么创建出来的。我们先来看下View的创建流程。总结如下所示:Activity执行onResume之后再ActivityThread中执行Activity的makeVisible方法。View的绘制流程包含了测量大小,测量位置,绘制三个流程;Activity的界面绘制是从mDoctor即根View开始的,也就是从mDoctor的测量大小,测量位置,绘制三个流程;

杨充 1289

有史以来最小的GIF/png/jpg/jpeg

昨天我对图像进行了 base64 编码,这样我就可以将它发送到 CouchDB 以测试我正在为客户编写的一些代码。它让我想起了我之前在远程服务器上设置 cookie 时所做的事情。基本上,一个小的 PHP 脚本被放在远程服务器上,它接受几个 GET 参数并根据它们的值设置一些 cookie。然后脚本输出一个 1x1 的透明 GIF。本地服务器上的 PHP 脚本生成了一个 IMG 标签,该标签链接到该图像并根据本地服务器上的 COOKIES 设置参数。

凌凌1301的博客 1417

从源码解析-Android中View的绘制流程及performTraversals方法

谈谈Activity的setContentView是怎么加载XML视图的 谈谈Activity的View怎么与View绘制工具ViewRootImpl关联的 在前面两篇文章中分析了View是如何跟绘制工具ViewRootImpl关联的,setContentView是如何把我们编写的xml视图添加到Activity中的,那今天就要分析下绘制工具ViewRootImpl是如何绘制我们Activit...

Mango先生的博客 4965

缠论 公式 自动画线 画笔 中枢 买卖点 源代码

【代码】缠论 公式 自动画线 画笔 中枢 买卖点 源代码。

weixin_40835859的博客 2万+

哨兵一号burst数据的下载和处理

在Sentinel - 1数据处理领域,其基本流程起始于从(ASF)下载原始压缩文件。这些文件规模颇为可观,常规大小约4GB,而部分数据的原文件甚至已攀升至7GB,对存储空间提出了严苛要求。从影像构成来看,每景Sentinel - 1影像由三个干涉宽幅(IW)模式子带组成,每个IW一般包含9个脉冲串(burst)。然而,在实际研究中,我们所关注的研究区域往往仅占据其中寥寥几个burst。

kangkangluoluo的博客 1964

Android应用层View绘制流程与源码分析

【工匠若水 http://blog.youkuaiyun.com/yanbober 转载烦请注明出处,尊重分享成果】1 背景还记得前面《Android应用setContentView与LayoutInflater加载解析机制源码分析》这篇文章吗?我们有分析到Activity中界面加载显示的基本流程原理,记不记得最终分析结果就是下面的关系:看见没有,如上图中id为content的内容就是整个View树的结构,所

工匠若水 14万+

同一台电脑使用模拟ModbusTcp主从通讯的时候,Wireshark抓取不到包

在使用ModBus Slave和Poll模拟主从通讯的时候,发现Wireshark怎么都抓取不到包怎么排查和解决?

HUJIANGMING的博客 703

View的绘制流程及源码分析

这篇文章主要讲解的是View的绘制流程以及源码分析,讲解这些的主要目的是为了能够在理解View的工作原理上更好的自定义View。 首先讲解一下布局文件是如何展现到屏幕上的。 一、布局文件是如何呈现在屏幕上的 我们从Activity的setContentView(R.layout.activity_main)入手了解UI绘制的起始过程。点进源码,我们会看到 Activity.java p...

很正经的程序员 1294

Mplus—交叉滞后面板模型(Cross-Lagged Panel Model, CLPM)

本文介绍交叉滞后模型相关知识,以及显变量模型与潜变量模型在Mplus中的语法。

m0_54401011的博客 1万+

uniapp ios原生插件开发 (framework,cocoapods)

已知UniApp的插件开发方式有两种, 第一种 Xcode Framework的方式,这种方式是官方指定的方式。 这种方式的优点就是简单直接, 但也有不足,比如当插件需要引入一些三方库时,操作起来就不是那么方便。 而使用Cocoapods则可以很方便的引入三方库。 接下来,本文探索使用Cocoapods的方式来进行UniApp插件开发。

Rey的技术博客 9823

深入解析View的绘制源码流程

View的绘制流程 今天来讲讲View的绘制流程吧,这一块也是我比较薄弱的地方,而且之前没有什么耐心去看这一块。今天就来学习这一块的知识点。主要分为3部分: View树的创建 ViewRootImpl的创建 真正的绘制流程开始performTraversals View树的创建 首先思考一个问题View的绘制从那里开始?关于这个问题我一开始也谷歌百度了很多东西,但是还是不能解决我的疑惑。所以今天我打算从根本上解决这个问题——从Activity的setContentView开始看。下面开始我的

weixin_37873786的博客 882

(6):单相三绕组变压器的拉氏变换数学模型和仿真模型

本节详细推导了基于耦合电路的单相三绕组变压器考虑铁心损耗情况下的拉普拉斯变换数学模型,并据此用Matlab/Simulink的传递函数模块搭建了相应的仿真模型,仿真结果表明所建立的数学模型和仿真模型都是正确的。本文的贡献是建立了考虑铁心损耗的单相三绕组变压器基于拉氏变换象函数的数学模型,为使用Simulink传递函数模块实现单相三绕组变压器的仿真模型提供了一条途径,所采用的建模方法和技巧具有启发作用,值得借鉴。

weixin_45670943的博客 372

Android View原理解析之绘制流程(draw)

自定义View是Android进阶路线上必须攻克的难题,而在这之前就应该先对View的工作原理有一个系统的理解。本系列将分为4篇博客进行讲解,本文主要对View的绘制流程(draw)进行讲解。

CodingEnding的博客 1457

基于STM32设计的老人摔倒检测报警系统(OneNet+MQTT)(235)

基于STM32设计的老人摔倒检测报警系统,不仅能够实时监测老人的位置信息,方便在紧急情况下快速定位,还能通过陀螺仪模块精确检测老人的身体姿态,一旦判断为摔倒状态,系统将立即触发蜂鸣器报警,并通过4G网络向指定联系人发送短信警示,确保老人能够迅速得到援助。此外,系统还支持老人主动按下设备上的按键发送求助短信,增强了系统的灵活性和实用性。

4690

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Android中View的绘制流程

一、 摘要 介绍Android View的绘制流程,引出后续的异步消息、事件分发。 二、 ViewRootImpl 1. ViewRootImpl是什么 在API文档中如此描述ViewRootImpl: /** * The top of a view hierarchy, implementing the needed protocol between View * and the Wind...

进击的小宇宙 4682

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

从invalidate分析view绘制流程

1.前言 关于view的绘制流程,现在网上一查,就会直接告诉你,view的绘制流程是先onMeasure,然后onLayout,在最后onDraw,没错,绘制流程确实也是这样。所以我们今天要讨论的话题除了那三大方法内部到底做了什么,还要知道这个流程是怎么来的。这样大家就会对view的绘制过程有一个比较清晰的认识。 这里我想从view的一些常用方法来进行研究,就从invalidate这个方法开始吧。...

你缺少想象力的博客 4113

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

开源项目源码解析-View 绘制流程

View 绘制流程 本文为 Android 开源项目源码解析 公共技术点中的 View 绘制流程 部分 分析者:lightSky View 绘制机制 1. View 树的绘图流程 当 Activity 接收到焦点的时候,它会被请求绘制布局,该请求由Android framework 处理.绘制是从根节点开始,对布局树进行 measure 和 draw 。整个 View 树的绘图

第四维空间的专栏 940

一文彻底搞懂Android View的绘制流程

我们都知道,PhoneWindow是Android系统中最基本的窗口系统,每个Activity会创建一个。同时,PhoneWindow也是Activity和View系统交互的接口。DecorView本质上是一个FrameLayout,是Activity中所有View的祖先...

IT元老的博客 6128

Android View的绘制流程

Android View的绘制三大流程 View的mesure、layout、draw三大流程。本文将详细讲解View的三大流程,阅读本文最好有牢固的Android基础,并且对Android View的基本结构有所了解。View的三大流程非常的重要,感觉现在面试必问。 同时,这个流程熟悉对于提升我们的开发水平也有很大的帮助。 在实际的开发中解决那种坑逼的问题时,熟悉三大流程必将事倍功半。 本文...

samuelnotes的专栏 4989

View绘制流程源码解析

1 View能在子线程更新吗 1 View绘制流程的主要对象 2 View绘制流程的函数调用

Vincent的博客 807

Android视图绘制流程完全解析,带你一步步深入了解View(二)

在上一篇文章中,我带着大家一起剖析了一下LayoutInflater的工作原理,可以算是对View进行深入了解的第一步吧。那么本篇文章中,我们将继续对View进行深入探究,看一看它的绘制流程到底是什么样的。如果你还没有看过我的上一篇文章,可以先去阅读 Android LayoutInflater原理分析,带你一步步深入了解View(一) 。 相信每个Android程序员都知道,我们每天的开发工作当中都在不停地跟View打交道,Android中的任何一个布局、任何一个控件其实都是直接或间接继承自View的,

郭霖的专栏 24万+

再谈Android View绘制流程

笔者在这里提醒读者,Android的View是UI的高级抽象,我们平时使用的XML文件也好,本质是设计模式中的一种策略模式,其View可以理解为一种底层UI显示的Request。各种VIew的排布,来自于开发者编写的XML文件,或动态增添删除View,这一系列的集合即一种策略。而这种策略最终会被Android系统解析为一种Request请求。什么意思呢?就是应用进程在此充当绘制的客户端,而服务器是谁?记住,即便屏幕前是我们所描绘的某种策略绘制的UI,那也是Surface系统服务器的Response表现。

qq_40900926的博客 1525

谈谈 View 绘制流程

注:本文使用 sdk 23 作为源码参考。 前言 ViewRootImpl#performTraversals() ViewRootImpl#performMeasure() ViewRootImpl#performLayout() ViewRootImpl#performDraw() some tips onDraw() dispatchDraw() 前言 关于 View 的绘制流

joker 878

Android源码分析之View的绘制流程

Android View的绘制流程详解(包括View的来龙去脉) 对于Android开发者来说,View无疑是开发中经常接触的,包括它的事件分发机制、测量、布局、绘制流程等,如果要自定义一个View,那么应该对以上流程有所了解、研究。本系列文章将会为大家带来View的工作流程详细解析。在深入接触View的测量、布局、绘制这三个流程之前,我们从Activity入手,看看从Activity创建后到V...

博由心生,福泽一生 1477

从源码的角度分析View的绘制流程

温馨提示:以下源码分析会截取源码进行说明,部分方法源码较长会只保留关键代码,其他代码用…省略 View的绘制入口是ActivityThread#handleResumeActivity final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean re...

isJoker的博客 255
上一篇: Handler源码解析系列一
下一篇: 剑指Offer数组习题-合并两个有序数组
丸子哒哒哒
博客等级 码龄12年 31粉丝 50原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值