framework源码读后感

2023-05-16

View部分

1.ViewParent

  今天查看了ViewGroup,ViewRootImpl和ViewParent的部分源代码,前面的两个类都实现了ViewParent接口。ViewGroup是一个抽象类,所以它无需实现ViewParent接口里面的方法,既然这样那么ViewGroup的子类应该会实现ViewParent里面的方法,就以requestLayout()方法为例找一找好了,于是我去找了FrameLayout类,搜索,竟然没有
requestLayout()方法的实现,这个可是具体类啊,竟然没有实现这个方法,不科学啊,不科学,然而这个类里面有一处对requestLayout()方法的调用,既然都没实现,那怎么可以调用呢?在ide里面鼠标点击过去一看,你猜怎么着?竟然跳转到了View类里面的requestLayout()方法,这个方法不是实现了某接口的方法,然而它却是ViewParent中方法
的一个同名方法,还能有这样的操作???
在这里插入图片描述

  (1)关于ViewParent的理解
这是一个接口,ViewGroup和ViewRootImpl类都实现了这个接口,ViewRootImpl类直接实现了requestLayout()方法,会对整个view树进行遍历执行measure,layout,draw操作。

  sdk里面的DecorView类的ViewParent变量指向的正是ViewRootImpl,requestLayout()方法层层向上(往view树根的方向)调用,当到达DecorView的requestLayout()方法调用的时候就会触发ViewRootImpl的requestLayout()方法,从而触发measure,layout,draw的三大流程。
  (2)WindowManager.AddView
在ActivityThread类,进行到activity生命周期的onResume()方法的时候,会有addView的
操作,这个调用流程大致是WindowManager=>WindowManagerImpl=>WindowManagerGlobal=>ViewRootImpl。
在ViewRootImpl中的setView方法里面,DecorView的ViewParent会被赋值为ViewRootImpl。

ViewRootImpl.java
// setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
//        int userId){
//   ...
//   view.assignParent(this);
//   ...
// }

  (3)这里面有个疑问就是,每一层普通View的ViewParent是在何时赋值的呢?
  activity#setContentView(int)=>PhoneWindow#setContentView
LayoutInflater#inflate=>LayoutInflater#rInflate,此方法中有个while循环,在调用viewGroup.addView()方法的时候,在addView方法的内部继续找ViewGroup#addViewInner找到了蛛丝马迹,ViewGroup在调用addViewInner方法的时候,在方法的内部对子view的ViewParent属性进行了赋值。

private void addViewInner(View child, int index, LayoutParams params,
            boolean preventRequestLayout) {
    ...
    if (child.getParent() != null) {
        throw new IllegalStateException("The specified child already has a parent. " +
                "You must call removeView() on the child's parent first.");
    }
    ...
    // tell our children
    if (preventRequestLayout) {
        child.assignParent(this);
    } else {
        child.mParent = this;
    }
    ...
}

这段源码的追溯实在坎坷,如果能调试一下就更有把握确定这个调用顺序了。

2.Window

  Window是一个抽象类,它唯一的实现类是PhoneWindow类,它有一个WindowManager类型的属性,何时赋值的呢?
  这个属性的赋值是在ActivityThread中的handleLaunchActivity(…)方法=>performLaunchActivity(…)方法里面在反射实例化完成Activity和Application实例后,调用Activity的attach(…)方法的时候,在attach方法中创建了PhoneWindow对象,并调用了Window的setWindowManager方法对WindowManager属性进行了赋值。

3.View.invalidate

  invalidate()方法只会触发三大流程中的draw流程,measure和layout并不会触发,那么invalidate()调用后框架层是如何执行的呢?看了一篇博客,说类似requestLayout()方法层层向viewParent方向调用,最终会调用到ViewRootImpl.java中的方法里面去,这个时候就会执行一个scheduleTraversal()方法,进而触发draw流程。捋了一遍源码还没看太明白。还得再捋一遍。
  View调用自己的ViewParent属性的如下方法ViewParent invalidateChildInParent(int[] location, Rect r)继续返回ViewParent(子类)的ViewParent属性,这个方法在ViewGroup.java和ViewRootImpl.java中进行了实现,这样就会一直向view树的树根DecorView的ViewParent(ViewRootImpl),进而调用其ViewParent invalidateChildInParent(int[] location, Rect r)方法,从而触发三大流程的draw流程,就实现了view重新绘制的操作,基本捋明了。

4.activity

  四大组件activity, service, broadcast receiver, content provider,其中activity是负责页面展示的,但是其实activity本身是无法显示内容的,之所以能显示内容是因为activity里面有一个window属性,真正的显示内容是window实现的,这…为什么不直接用window作为显示内容的一大组件呢?还要多搞一个activity呢?不知道鲁宾是怎么想的?
  Activity的本质是什么呢?在源码中可以看到Activity也不过是个普通的java类,继承了ContextThemeWrapper类,实现了若干接口,嗯,应该是framework框架层赋予了它四大组件之一的地位。

x.sdk源码中的位运算

//00100000
//|
//00010000
//00110000
//0x30

取反和与运算
//~
//00110000
//11001111
//&
//11111111
//11001111
	static final int PFLAG_HAS_BOUNDS   = 0x00000010;
    static final int PFLAG_DRAWN        = 0x00000020;
    static final int PFLAG_FORCE_LAYOUT = 0x00001000;
    /*
     * 在android sdk framework源码里面有许多的位运算,其中赋值一般使用|或运算符,
     * 判断一般使用&与运算符,清空一般使用&和~位运算符.
     */
    void bit() {
//        int r = PFLAG_DRAWN | PFLAG_HAS_BOUNDS;
//        System.out.println(r);
//        System.out.println(Integer.toHexString(r));
//
//        r |= PFLAG_FORCE_LAYOUT;
//
//        if ((r & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) {
//            System.out.println("yes");
//        } else {
//            System.out.println("no");
//        }

        int privateFlags = 0;
        //为某位赋值
        privateFlags |= (PFLAG_DRAWN | PFLAG_HAS_BOUNDS);

        System.out.println(privateFlags);

        //清空某位的值
        privateFlags &= ~(PFLAG_DRAWN | PFLAG_HAS_BOUNDS);
        System.out.println(privateFlags);

        //为某位赋值
        privateFlags |= PFLAG_FORCE_LAYOUT;
        System.out.println(privateFlags);

        //清空某位的值
        privateFlags &= ~PFLAG_FORCE_LAYOUT;
        System.out.println(privateFlags);
    }

开源项目

BlockCanary

  监视app的UI线程阻塞,原理是什么?
今天看了一篇BC的分析文章,感觉涨了不少知识,虽然有的代码分析还是没看太懂,但是感觉知道了不少以前不知道的东西,这么说来原理也挺简单的。就是在消息处理前记录一下开始的时间戳,消息处理结束后再记录一下时间戳,减去开始的时间戳,如果时间差大于预先设置的阈值就可以认为是发生了卡顿。

  原理就是这么个原理,但是这里有一个问题,如何在消息处理前和处理后插入自己的记录时间戳的代码呢?前方高能,这里看一下代码

public static void loop() {
    for (;;) {
        Message msg = queue.next(); // might block

        // This must be in a local variable, in case a UI event sets the logger
        final Printer logging = me.mLogging;
        if (logging != null) {
            logging.println(">>>>> Dispatching to " + msg.target + " " +
                    msg.callback + ": " + msg.what);
        }

        ...
        msg.target.dispatchMessage(msg);
        ...

        if (logging != null) {
            logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
        }
    }
}

  这里有2个if判断,条件是其中的Printer类型的变量logging是否为空,这个Printer是个接口,Looper类支持Printer自定义并传入,这样一来,我们就可以在回调方法的参数里面根据log的字符串来判断何时开始何时结束并记录和计算时间差了,大佬就是大佬啊,佩服!佩服!

public interface Printer {
    void println(String x);
}

public void setMessageLogging(@Nullable Printer printer) {
    mLogging = printer;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

framework源码读后感 的相关文章

  • 快速排序总结

    文章内容和代码来自 漫画算法 和数据结构教材 现进行一下代码编写练习 1 双边循环法 span class token comment 双边循环法 xff0c 从左右两端分别向中间进行比较和交换数据 递归实现 span span class

随机推荐

  • 堆排序总结

    本文内容来源于 漫画算法 和数据结构教材 这里提到的堆是一个二叉堆 xff0c 本质上是一颗完全二叉树 堆排序只需要一个记录大小的辅助空间 1 java实现 span class token comment 下沉调整 64 param ar
  • 计数排序

    本文内容和代码来自 漫画算法 之前练习的冒泡排序 鸡尾酒排序 快速排序 堆排序都是基于元素比较和位置元素交换实现的 xff0c 有一些特殊的排序并不基于元素比较 xff0c 如计数排序 桶排序 基数排序 以计数排序来说 xff0c 这种排序
  • 桶排序

    本文内容和代码来源于 漫画算法 针对计数排序的局限性 xff0c 桶排序做出了弥补 xff0c 时间复杂度同样是线性级 类似于计数排序所创建的统计数组 xff0c 桶排序需要创建若干个桶来协助排序 那么桶排序中所谓的 桶 xff0c 又是什
  • 归并排序

    本文内容和代码来源于数据结构教材 归并排序 Merging Sort 是又一类不同的排序方法 34 归并 34 的含义是将2个或2个以上的有序表组合成1个新的有序表 无论是顺序存储还是链表存储结构 xff0c 都可在O m 43 n 的时间
  • 插入排序

    文章内容来源于数据结构教材 C语言版 教材讲解了4种插入排序算法 xff0c 分别为 1 直接插入排序 2 折半插入排序 3 2 路插入排序 4 表插入排序 还有一个希尔排序 属于插入排序分类 本文只将1 2 xff0c 两种算法进行了实践
  • 希尔排序

    本文内容来源于数据结构教材 C语言版 希尔排序 Shell s Sort xff0c 又称缩小增量排序 Diminishing Increment Sort xff0c 它也是一种属插入排序类的方法 xff0c 但在时间效率上较前几种插入排
  • Java swing绘制柱状图和饼图

    15 14编写程序 xff0c 使用条形图显示作业 平时测验 其中考试和期末考试占总成绩的百分比 假设作业占20 用红色显示 xff0c 平时测验占10 用蓝色显示 xff0c 其中考试占30 用绿色显示 xff0c 期末考试占40 用橙色
  • Java注解(Annotation)学习

    xff08 本文内容来源于疯狂Java讲义 xff0c 感谢 xff09 注解 Annotation Annotation是代码里的特殊标记 xff0c 这些标记可以在编译 类加载 运行时被读取 xff0c 并执行相应的处理 通过使用注解
  • Java Swing制作古老的打砖块游戏

    最近研究了一下古老的Java Swing xff0c 研究之余 xff0c 突发奇想开发了一个打砖块小游戏 首先看一下效果图 具体过程 1 游戏框架搭建1 1步骤 2 开发过程2 1各种游戏对象的绘制2 2游戏对象的运动2 3小球和砖块的碰
  • 局域网下yum代理配置

    需求背景 由于公司局域网内无法连接外网 xff0c 只有一台服务器能连接外网 xff0c 可选择搭建squid作为代理 xff0c 供无法访问外网的服务器 xff0c 安装软件使用 安装Squid yum install y squid 配
  • AndroidX迁移和吐槽

    最近引入一个第三方 xff0c 需要使用androidx扩展库 xff0c compile后发现与旧的support库无法兼容 xff0c 于是逐个的把support的库换成了androidx系列 xff0c 倒腾半天 xff0c 失败无数
  • Android中的事件

    有内容参考了别人的文章 xff0c 感谢作者 Input Events Event Listeners Event Handlers Touch Model Handling Focus https developer android co
  • Ubuntu19.10/20.04安装记录

    安装过程 官方网站下载 xff0c 搜索引擎搜索Ubuntu history version 找到19 10 xff0c 下载速度略慢 xff0c 大小大约2 3G 在Windows 上面使用UltraISO 试用版即可 刻录到u盘即可 重
  • android疑难问题收集

    1 自定义ViewGroup实现折叠展开 xff0c 离奇的折叠后又展开 在一个布局里面我参考网络代码实现了一个折叠展开的自定义viewgroup xff0c 其实是调用layout方法实现的折叠和展开 xff0c 最近出现一个bug xf
  • 开发错误笔记

    开发环境IDE Android Studio环境错误 1 布局引用的资源文件不存在的错误提示 Caused by android content res Resources NotFoundException Caused by org x
  • 程序员的送外卖经历

    今天我的一个朋友跟我发消息说 xff0c 看着外面刮着大风 xff0c 自己在屋子里面 xff0c 靠着暖气 xff0c 真是幸福啊 其实也没啥 xff0c 我这个朋友去年送了半年外卖 xff0c 大冬天依然在送 xff0c 户外骑着电动车
  • fragment添加失败错误查找

    根据源码查找原因 span class token class name Caused span by span class token operator span span class token class name span clas
  • Swing实现模仿HTML5模拟时钟特效

    自从研究了Java Swing的Graphics xff0c 觉得能按照自己的想法画出一些东西 xff0c 还是挺有意思的 xff0c 之前学习Java Swing的时候练习过一个模拟时钟 xff0c 自己觉得不错 xff0c 后来看到这个
  • jdk|adb命令行使用总结

    记录jdk的命令行使用记录 javac 1 java命令行编译多个源文件 javac d Example1 java Example2 java Example1是主类 xff0c 要用到Exmaple2 执行 xff1a java com
  • framework源码读后感

    View部分 1 ViewParent 今天查看了ViewGroup xff0c ViewRootImpl和ViewParent的部分源代码 xff0c 前面的两个类都实现了ViewParent接口 ViewGroup是一个抽象类 xff0