编程进阶网编程进阶网
  • 基础组成体系
  • 程序编程原理
  • 异常和IO系统
  • 六大设计原则
  • 设计模式导读
  • 创建型设计模式
  • 结构型设计模式
  • 行为型设计模式
  • 设计模式案例
  • 面向对象思想
  • 基础入门
  • 高级进阶
  • JVM虚拟机
  • 数据集合
  • Java面试题
  • C语言入门
  • C综合案例
  • C标准库
  • C语言专栏
  • C++入门
  • C++综合案例
  • C++专栏
  • HTML
  • CSS
  • JavaScript
  • 前端专栏
  • Swift
  • iOS入门
  • 基础入门
  • 开源库解读
  • 性能优化
  • Framework
  • 方案设计
  • 媒体音视频
  • 硬件开发
  • Groovy
  • 常用工具
  • 大厂面试题
  • 综合案例
  • 网络底层
  • Https
  • 网络请求
  • 故障排查
  • 专栏
  • 数组
  • 链表
  • 栈
  • 队列
  • 树
  • 递归
  • 哈希
  • 排序
  • 查找
  • 字符串
  • 其他
  • Bash脚本
  • Linux入门
  • 嵌入式开发
  • 代码规范
  • Markdown
  • 开发理论
  • 开发工具
  • Git管理
  • 百宝箱
  • 开源协议
  • 技术招聘
  • 测试经验
  • 职场提升
  • 技术模版
  • 关于我
  • 目标清单
  • 学习框架
  • 育儿经验
  • 我的专栏
  • 底层能力
  • 读书心得
  • 随笔笔记
  • 职场思考
  • 中华历史
  • 经济学故事
  • 基础组成体系
  • 程序编程原理
  • 异常和IO系统
  • 六大设计原则
  • 设计模式导读
  • 创建型设计模式
  • 结构型设计模式
  • 行为型设计模式
  • 设计模式案例
  • 面向对象思想
  • 基础入门
  • 高级进阶
  • JVM虚拟机
  • 数据集合
  • Java面试题
  • C语言入门
  • C综合案例
  • C标准库
  • C语言专栏
  • C++入门
  • C++综合案例
  • C++专栏
  • HTML
  • CSS
  • JavaScript
  • 前端专栏
  • Swift
  • iOS入门
  • 基础入门
  • 开源库解读
  • 性能优化
  • Framework
  • 方案设计
  • 媒体音视频
  • 硬件开发
  • Groovy
  • 常用工具
  • 大厂面试题
  • 综合案例
  • 网络底层
  • Https
  • 网络请求
  • 故障排查
  • 专栏
  • 数组
  • 链表
  • 栈
  • 队列
  • 树
  • 递归
  • 哈希
  • 排序
  • 查找
  • 字符串
  • 其他
  • Bash脚本
  • Linux入门
  • 嵌入式开发
  • 代码规范
  • Markdown
  • 开发理论
  • 开发工具
  • Git管理
  • 百宝箱
  • 开源协议
  • 技术招聘
  • 测试经验
  • 职场提升
  • 技术模版
  • 关于我
  • 目标清单
  • 学习框架
  • 育儿经验
  • 我的专栏
  • 底层能力
  • 读书心得
  • 随笔笔记
  • 职场思考
  • 中华历史
  • 经济学故事
  • 1.1App启动流程梳理
  • 1.2ActivityThread分析
  • 1.3Context设计思想
  • 2.1Activity基础介绍
  • 2.2Activity启动流程
  • 2.3Activity布局创建
  • 2.4Activity布局绘制
  • 2.5Service基础介绍
  • 2.6Service启动流程
  • 2.7Receiver广播基础
  • 2.8Receiver深入原理
  • 2.9ContentProvider分析
  • 2.10Fragment实践
  • 2.11Intent深入思考
  • 3.1Paint和Canvas
  • 3.2View的绘制基础
  • 3.3onMeasure流程设计
  • 3.4onLayout流程设计
  • 3.5onDraw流程设计
  • 3.6View工作原理
  • 3.7View刷新设计流程
  • 3.8自定义View控件
  • 3.9自定义ViewGroup控件
  • 4.1Handler基础使用
  • 4.2消息机制流程分析
  • 4.3Handler深度解析
  • 4.4Message深度理解
  • 4.5MessageQueue解析
  • 4.6Looper深度解析
  • 4.7理解Handler同步屏障
  • 4.8ThreadLocal分析
  • 4.9ThreadLocal场景
  • 5.1View事件设计思考
  • 5.2View滑动冲突处理
  • 5.3View事件源码分析
  • 5.4View事件总结案例
  • 6.1DecorView设计思想
  • 6.2视图的载体View
  • 6.3视图管理者Window
  • 6.4窗口管理服务WMS
  • 6.5布局解析者Inflater
  • 7.1AsyncTask深入介绍
  • 7.2HandlerThread设计
  • 7.3IntentService设计
  • 8.1IPC通信方式介绍
  • 8.2AIDL进程间通信
  • 8.7Binder通信机制设计
  • /zh/android/basic/9.1注解设计思想和原理.html
  • 9.2APT技术设计详解
  • 9.3APT多种案例实践

6.2视图的载体View

目录介绍

  • 00.View简单介绍
  • 01.View的生命周期
  • 02.生命周期作用

00.View简单介绍

  • 先看一段介绍
    • This class represents the basic building block for user interface components. A Viewoccupies a rectangular area on the screen and is responsible for drawing and event handling.
  • View是屏幕上的一块矩形区域,负责界面的绘制与触摸事件的处理,它是一种界面层控件的抽象,所有的控件都继承自View。
    • View是Android显示框架中较为复杂的一环,首先是它的生命周期会随着Activity的生命周期进行变化,掌握View的生命周期对我们自定义View有着重要的意义。另一个方面View从ViewRoot.performTraversals()开始经历measure、layout、draw三个流程最终显示在用户面前,用户在点击屏幕时,点击事件随着Activity传入Window,最终由ViewGroup/View进行分发处理。

01.View的生命周期

  • 在View中有诸多回调方法,它们在View的不同生命周期阶段调用,常用的有以下方法。写一个简单的自定义View来观察View与Activity的生命周期变化。
    public class CustomView extends View {
    
        private static final String TAG = "View";
    
        public CustomView(Context context) {
            super(context);
            Log.d(TAG, "CustomView()");
        }
    
        public CustomView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            Log.d(TAG, "CustomView()");
        }
    
        public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            Log.d(TAG, "CustomView()");
        }
    
        /**
         * View在xml文件里加载完成时调用
         */
        @Override
        protected void onFinishInflate() {
            super.onFinishInflate();
            Log.d(TAG, "View onFinishInflate()");
        }
    
        /**
         * 测量View及其子View大小时调用
         */
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            Log.d(TAG, "View onMeasure()");
        }
    
        /**
         * 布局View及其子View大小时调用
         */
        @Override
        protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
            super.onLayout(changed, left, top, right, bottom);
            Log.d(TAG, "View onLayout() left = " + left + " top = " + top + " right = " + right + " bottom = " + bottom);
        }
    
        /**
         * View大小发生改变时调用
         */
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            Log.d(TAG, "View onSizeChanged() w = " + w + " h = " + h + " oldw = " + oldw + " oldh = " + oldh);
        }
    
        /**
         * 绘制View及其子View大小时调用
         */
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            Log.d(TAG, "View onDraw()");
        }
    
        /**
         * 物理按键事件发生时调用
         */
        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            Log.d(TAG, "View onKeyDown() event = " + event.getAction());
            return super.onKeyDown(keyCode, event);
        }
    
        /**
         * 物理按键事件发生时调用
         */
        @Override
        public boolean onKeyUp(int keyCode, KeyEvent event) {
            Log.d(TAG, "View onKeyUp() event = " + event.getAction());
            return super.onKeyUp(keyCode, event);
        }
    
        /**
         * 触摸事件发生时调用
         */
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            Log.d(TAG, "View onTouchEvent() event =  " + event.getAction());
            return super.onTouchEvent(event);
        }
    
        /**
         * View获取焦点或者失去焦点时调用
         */
        @Override
        protected void onFocusChanged(boolean gainFocus, int direction, @Nullable Rect previouslyFocusedRect) {
            super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
            Log.d(TAG, "View onFocusChanged() gainFocus = " + gainFocus);
        }
    
        /**
         * View所在窗口获取焦点或者失去焦点时调用
         */
        @Override
        public void onWindowFocusChanged(boolean hasWindowFocus) {
            super.onWindowFocusChanged(hasWindowFocus);
            Log.d(TAG, "View onWindowFocusChanged() hasWindowFocus = " + hasWindowFocus);
        }
    
        /**
         * View被关联到窗口时调用
         */
        @Override
        protected void onAttachedToWindow() {
            super.onAttachedToWindow();
            Log.d(TAG, "View onAttachedToWindow()");
        }
    
        /**
         * View从窗口分离时调用
         */
        @Override
        protected void onDetachedFromWindow() {
            super.onDetachedFromWindow();
            Log.d(TAG, "View onDetachedFromWindow()");
        }
    
        /**
         * View的可见性发生变化时调用
         */
        @Override
        protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
            super.onVisibilityChanged(changedView, visibility);
            Log.d(TAG, "View onVisibilityChanged() visibility = " + visibility);
        }
    
        /**
         * View所在窗口的可见性发生变化时调用
         */
        @Override
        protected void onWindowVisibilityChanged(int visibility) {
            super.onWindowVisibilityChanged(visibility);
            Log.d(TAG, "View onWindowVisibilityChanged() visibility = " + visibility);
        }
    }

1.1 Activity与View的生命周期

  • Activity create
    2019-08-22 13:48:02.423 31303-31303/org.yczbj.ycrefreshview D/小杨测试--View--: CustomView()
    2019-08-22 13:48:02.423 31303-31303/org.yczbj.ycrefreshview D/小杨测试--View--: View onFinishInflate()
    2019-08-22 13:48:02.618 31303-31303/org.yczbj.ycrefreshview D/小杨测试--Activity--: onCreate
    2019-08-22 13:48:02.627 31303-31303/org.yczbj.ycrefreshview D/小杨测试--Activity--: onStart
    2019-08-22 13:48:02.630 31303-31303/org.yczbj.ycrefreshview D/小杨测试--Activity--: onResume
    2019-08-22 13:48:02.670 31303-31303/org.yczbj.ycrefreshview D/小杨测试--View--: View onAttachedToWindow()
    2019-08-22 13:48:02.670 31303-31303/org.yczbj.ycrefreshview D/小杨测试--View--: View onWindowVisibilityChanged() visibility = 0
    2019-08-22 13:48:02.670 31303-31303/org.yczbj.ycrefreshview D/小杨测试--View--: View onVisibilityChanged() visibility = 0
    2019-08-22 13:48:02.687 31303-31303/org.yczbj.ycrefreshview D/小杨测试--View--: View onMeasure()
    2019-08-22 13:48:02.709 31303-31303/org.yczbj.ycrefreshview D/小杨测试--View--: View onMeasure()
    2019-08-22 13:48:02.713 31303-31303/org.yczbj.ycrefreshview D/小杨测试--View--: View onSizeChanged() w = 1080 h = 30 oldw = 0 oldh = 0
    2019-08-22 13:48:02.714 31303-31303/org.yczbj.ycrefreshview D/小杨测试--View--: View onLayout() left = 0 top = 0 right = 1080 bottom = 30
    2019-08-22 13:48:02.993 31303-31303/org.yczbj.ycrefreshview D/小杨测试--View--: View onDraw()
    2019-08-22 13:48:03.058 31303-31303/org.yczbj.ycrefreshview D/小杨测试--View--: View onWindowFocusChanged() hasWindowFocus = true
  • Activity pause
    2019-08-22 13:50:02.843 31303-31303/org.yczbj.ycrefreshview D/小杨测试--Activity--: onPause
    2019-08-22 13:50:02.866 31303-31303/org.yczbj.ycrefreshview D/小杨测试--View--: View onWindowFocusChanged() hasWindowFocus = false
    2019-08-22 13:50:03.343 31303-31303/org.yczbj.ycrefreshview D/小杨测试--View--: View onWindowVisibilityChanged() visibility = 8
    2019-08-22 13:50:03.369 31303-31303/org.yczbj.ycrefreshview D/小杨测试--Activity--: onStop
    2019-08-22 13:50:03.375 31303-31303/org.yczbj.ycrefreshview D/小杨测试--View--: View onVisibilityChanged() visibility = 4
  • Activity resume
    2019-08-22 13:50:57.229 31303-31303/org.yczbj.ycrefreshview D/小杨测试--Activity--: onStart
    2019-08-22 13:50:57.232 31303-31303/org.yczbj.ycrefreshview D/小杨测试--Activity--: onResume
    2019-08-22 13:50:57.233 31303-31303/org.yczbj.ycrefreshview D/小杨测试--View--: View onVisibilityChanged() visibility = 0
    2019-08-22 13:50:57.237 31303-31303/org.yczbj.ycrefreshview D/小杨测试--View--: View onWindowVisibilityChanged() visibility = 0
    2019-08-22 13:50:57.277 31303-31303/org.yczbj.ycrefreshview D/小杨测试--View--: View onDraw()
    2019-08-22 13:50:57.299 31303-31303/org.yczbj.ycrefreshview D/小杨测试--View--: View onWindowFocusChanged() hasWindowFocus = true
  • Activity destory
    2019-08-22 13:51:46.013 31303-31303/org.yczbj.ycrefreshview D/小杨测试--Activity--: onStop
    2019-08-22 13:51:46.014 31303-31303/org.yczbj.ycrefreshview D/小杨测试--View--: View onVisibilityChanged() visibility = 4
    2019-08-22 13:51:46.019 31303-31303/org.yczbj.ycrefreshview D/小杨测试--Activity--: onDestroy
    2019-08-22 13:51:46.020 31303-31303/org.yczbj.ycrefreshview D/小杨测试--View--: View onDetachedFromWindow()
  • 来总结一下View的声明周期随着Activity生命周期变化的情况。

02.生命周期作用

  • 了解这些生命周期方法有什么作用呢?🤔其实这些方法在我们自定义View的时候发挥着很大的作用,我们来举几种应用场景。
  • 场景1:在Activity启动时获取View的宽高,但是在onCreate、onStart和onResume均无法获取正确的结果。这是因为在Activity的这些方法里,Viewed绘制可能还没有完成,我们可以在View的生命周期方法里获取。
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if(hasFocus){
            int width = view.getMeasuredWidth();
            int height = view.getMeasuredHeight();
        }
    }
  • 场景2:在Activity生命周期发生变化时,View也要做响应的处理,典型的有VideoView保存进度和恢复进度。
    @Override
    protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
        super.onVisibilityChanged(changedView, visibility);
        //TODO do something if activity lifecycle changed if necessary
        //Activity onResume()
        if(visibility == VISIBLE){
            
        }
        //Activity onPause()
        else {
            
        }
    }
    
    @Override
    public void onWindowFocusChanged(boolean hasWindowFocus) {
        super.onWindowFocusChanged(hasWindowFocus);
    
        //TODO do something if activity lifecycle changed if necessary
        //Activity onResume()
        if (hasWindowFocus) {
        }
        //Activity onPause()
        else {
        }
    }
  • 场景3:释放线程、资源
    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        //TODO release resources, thread, animation
    }

其他介绍

01.关于博客汇总链接

  • 1.技术博客汇总
  • 2.开源项目汇总
  • 3.生活博客汇总
  • 4.喜马拉雅音频汇总
  • 5.其他汇总

02.关于我的博客

  • github:https://github.com/yangchong211
  • 知乎:https://www.zhihu.com/people/yczbj/activities
  • 简书:http://www.jianshu.com/u/b7b2c6ed9284
  • csdn:http://my.csdn.net/m0_37700275
  • 喜马拉雅听书:http://www.ximalaya.com/zhubo/71989305/
  • 开源中国:https://my.oschina.net/zbj1618/blog
  • 泡在网上的日子:http://www.jcodecraeer.com/member/content_list.php?channelid=1
  • 邮箱:yangchong211@163.com
  • 阿里云博客:https://yq.aliyun.com/users/article?spm=5176.100- 239.headeruserinfo.3.dT4bcV
  • segmentfault头条:https://segmentfault.com/u/xiangjianyu/articles
  • 掘金:https://juejin.im/user/5939433efe88c2006afa0c6e
贡献者: yangchong211
上一篇
6.1DecorView设计思想
下一篇
6.3视图管理者Window