摘要:这种自定义控件在原生控件提供的方法外,可以自己添加一些方法。从顶层父到子递归调用方法,方法又回调。
目录介绍
3.0.0.1 View的绘制需要经过哪些过程?有哪些常用回调方法?View的绘制流程的详细流程是怎样的?
3.0.0.2 View绘制流程,当一个TextView的实例调用setText()方法后执行了什么?请说一下原理……
3.0.0.3 requestLayout()、invalidate()与postInvalidate()有什么区别?
3.0.0.4 DecorView的作用是什么?DecorView中如何获取ContentView以及Activity所设置的View?ViewRootIml如何和DecorView建立联系?
3.0.0.5 getWidth()方法和getMeasureWidth()区别呢?为什么有时候用getWidth()或者getMeasureWidth()得到0?
3.0.0.6 平时写的自定义控件有哪些?如何优化自定义view?View的绘制流程说一下?自定义View的注意点?
3.0.0.7 View的wrap_content和match_parent效果一致的原因分析?getDefaultSize方法的处理逻辑?
3.0.0.8 ViewGroup(抽象类)的measure流程?getChildMeasureSpec获取子元素MeasureSpec的要点?
3.0.0.9 View的layout过程?View的layout()源码分析?LinearLayout的onLayout方法?View的测量宽高和最终宽高有什么区别?
3.0.1.0 draw的过程步骤是什么?View特殊方法setWillNotDraw是干什么用的?
3.0.1.1 View中x,y,translationX,translationY分别是什么?View平移时是否改变了left、top等原始参数?
3.0.1.2 MeasureSpec是什么?MeasureSpec的组成?测量模式SpecMode的类型和具体含义?MeasureSpec和LayoutParams的对应关系?
3.0.1.3 如何获取View的测量宽/高?如何在Activity启动时获得View的宽/高?Activity中获得View宽高的4种办法?
3.0.1.4 Activity启动到最终加载ViewRoot(执行三大流程)的流程是什么?
3.0.1.5 自定义View性能优化有哪些?针对异常销毁,自定义View如何优化?如何避免创建大量对象?
好消息博客笔记大汇总【15年10月到至今】,包括Java基础及深入知识点,Android技术博客,Python学习笔记等等,还包括平时开发中遇到的bug汇总,当然也在工作之余收集了大量的面试题,长期更新维护并且修正,持续完善……开源的文件是markdown格式的!同时也开源了生活博客,从12年起,积累共计500篇[近100万字],将会陆续发表到网上,转载请注明出处,谢谢!
链接地址:https://github.com/yangchong2...
如果觉得好,可以star一下,谢谢!当然也欢迎提出建议,万事起于忽微,量变引起质变!所有的笔记将会更新到GitHub上,同时保持更新,欢迎同行提出或者push不同的看法或者笔记!
3.0.0.1 View的绘制需要经过哪些过程?有哪些常用回调方法?View的绘制流程的详细流程是怎样的?
View的绘制需要经过哪些过程?
measure:测量View的宽和高
View的measure方法是final类型方法——表明该方法无法被重载
View的measure方法会调用onMeasure方法,onMeasure会调用setMeasuredDimension方法设置View宽/高的测量值
layout:确定View在父控件中的放置位置
draw:负责将View绘制在屏幕上。技术博客大总结
有哪些常用回调方法?
构造方法
onAttachToWindow:在包含View的Activity启动时调用
onDetachFromWindow:在包含View的Activity退出或者View被remove时回调
onVisibilityChanged:当View的可见状态发生改变时调用
比较重要的概念
ViewRoot:连接WindowManager(外界访问Window的入口)和DecorView(顶级View)的纽带,View的三大流程均是通过ViewRoot来完成的。
DecorView:顶级View
DecorView是顶级View,本质就是一个FrameLayout
包含了两个部分,标题栏和内容栏
内容栏id是content,也就是activity中setContentView所设置的部分,最终将布局添加到id为content的FrameLayout中
View的绘制流程的详细流程是怎样的?技术博客大总结
View的绘制流程是从ViewRoot的PerformTraversals方法开始的。大概的流程如下所示
performTraversals会依次调用performMeasure, performLayout, performDraw三个方法,这三个方法分别完成顶层View的measure,layout,draw方法,onMeasure又会调用所有子元素的measure过程,直到完成整个View树的遍历。同理,performLayout, performDraw的传递流程与performMeasure相似。唯一不同在于,performDraw的传递过程在draw方法中通过dispatchDraw实现,但没有本质区别。
Measure过程后可以调用getMeasureWidth和getMeasureHeight方法获取View测量后的宽高,与getWidth和getHeight的区别是:getMeasuredHeight()返回的是原始测量高度,与屏幕无关,getHeight()返回的是在屏幕上显示的高度。实际上在当屏幕可以包裹内容的时候,他们的值是相等的,只有当view超出屏幕后,才能看出他们的区别。当超出屏幕后,getMeasuredHeight()等于getHeight()加上屏幕之外没有显示的高度。
Layout过程确定View四个顶点的位置和实际的宽高。
Draw过程确定View的显示,只有draw方法完成后View的内容才会出现在屏幕上。
3.0.0.2 View绘制流程,当一个TextView的实例调用setText()方法后执行了什么?请说一下原理……
View的绘制流程主要分为三步:
onMeasure:测量视图的大小,从顶层父View到子View递归调用measure()方法,measure()调用onMeasure()方法,onMeasure()方法完成绘制工作。
onLayout:确定视图的位置,从顶层父View到子View递归调用layout()方法,父View将上一步measure()方法得到的子View的布局大小和布局参数,将子View放在合适的位置上。
onDraw:绘制最终的视图,首先ViewRoot创建一个Canvas对象,然后调用onDraw()方法进行绘制。onDraw()方法的绘制流程为
① 绘制视图背景。
② 绘制画布的图层。 技术博客大总结
③ 绘制View内容。
④ 绘制子视图,如果有的话。
⑤ 还原图层。
⑥ 绘制滚动条。
3.0.0.3 requestLayout()、invalidate()与postInvalidate()有什么区别?requestLayout()何时不会触发onDraw()?
invalidate() postInvalidate()
invalidate()该方法递归调用父View的invalidateChildInParent()方法,直到调用ViewRootImpl的invalidateChildInParent()方法,最终触发ViewRootImpl的performTraversals()方法,此时mLayoutRequestede为false,不会触发onMesaure()与onLayout()方法,有可能会触发onDraw()方法。
共同点:都是调用onDraw()方法,然后去达到重绘view的目的
区别:invalidate()用于主线程,postInvalidate()用于子线程
requestLayout()
该方法会递归调用父窗口的requestLayout()方法,直到触发ViewRootImpl的performTraversals()方法,此时mLayoutRequestede为true,会触发onMesaure()与onLayout()方法,不一定会触发onDraw()方法。
当view确定自身已经不再适合现有的区域时,该view本身调用这个方法要求parent view(父类的视图)重新调用他的onMeasure、onLayout来重新设置自己位置。特别是当view的layoutparameter发生改变,并且它的值还没能应用到view上时,这时候适合调用这个方法requestLayout()。requestLayout调用onMeasure和onLayout,不一定调用onDraw技术博客大总结
如何选择
一般说来需要重新布局就调用requestLayout()方法,需要重新绘制就调用invalidate()方法。
requestLayout()何时不会触发onDraw()?
如果没有改变控件的leftrighttopbottom就不会触发onDraw()
invalidate()在什么情况下不会触发onDraw?
在ViewGroup中,invalidate默认不重新绘制子view。
如何让ViewGroup在invalidate时会触发onDraw?技术博客大总结
本质需要将ViewGroup的dirtyOpaque设置为false
1.在构造函数中调用setWillNotDraw(false);
2.给ViewGroup设置背景。调用setBackground。
3.0.0.4 DecorView的作用是什么?DecorView中如何获取ContentView以及Activity所设置的View?ViewRootIml如何和DecorView建立联系?
DecorView的作用是什么?
DecorView是顶级View,本质就是一个FrameLayout
包含了两个部分,标题栏和内容栏,内容栏id是content,也就是activity中setContentView所设置的部分,最终将布局添加到id为content的FrameLayout中技术博客大总结
DecorView中如何获取ContentView以及Activity所设置的View?
获取content:ViewGroup content = findViewById(R.android.id.content)
获取设置的View:content.getChidlAt(0)
ViewRootIml如何和DecorView建立联系?技术博客大总结
Activity对象在ActivityThread中创建完毕后,会将DecorView添加到Window中
同时会创建ViewRootImpl,调用ViewRoot的setView方法将ViewRootImpl和DevorView建立关联
root = new ViewRootImpl(view.getContext(), display); root.setView(view, wparams, panelParentView);
ViewRoot为什么要和DecorView建立关联
DecorView等View的三大流程需要通过ViewRoot完成
3.0.0.5 getWidth()方法和getMeasureWidth()区别呢?为什么有时候用getWidth()或者getMeasureWidth()得到0?
getWidth()方法和getMeasureWidth()区别呢
getMeasureWidth()
getMeasureWidth()方法在measure()过程结束后就可以获取到了,另外,getMeasureWidth()方法中的值是通过setMeasuredDimension()方法来进行设置的
这里mMeasuredWidth & MEASURED_SIZE_MASK表示的是测量阶段结束之后,view真实的值。
public final int getMeasuredWidth() { return mMeasuredWidth & MEASURED_SIZE_MASK; }
getWidth()
getWidth()方法要在layout()过程结束后才能获取到,getWidth()方法中的值则是通过视图右边的坐标减去左边的坐标计算出来的。
mRight和mLeft是什么值,是在什么时候被设置的。具体看layout()过程中源码
@ViewDebug.ExportedProperty(category = "layout") public final int getWidth() { return mRight - mLeft; }
为什么有时候用getWidth()或者getMeasureWidth()得到0
问题描述:使用getMeasuredWidth()和getMeasuredHeight()方法,无论是在onCreate()、onStart()、onResume()中调用,都无法得到控件的长度、和宽度。如下图,测量的结果为0。
解释:技术博客大总结
因为View的Measure过程和Activity的生命周期方法不是同步执行的,所以无法保证Activity执行了onCreate()、onStart()、onResume()时某个View已经测量完毕了,如果View还没有测量完毕,那么获得宽/高就是0。
后来觉得这种解释有点牵强,比如
解决控件测量宽高问题
如下所示
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); test(); } @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); getWidth(4); } private void test(){ getWidth(1); marqueeView.measure(0, 0); getWidth(2); marqueeView.post(new Runnable() { @Override public void run() { getWidth(3); } }); } private void getWidth(int a){ int width2 = marqueeView.getWidth(); int measuredWidth2 = marqueeView.getMeasuredWidth(); Log.e(a+"MainActivity-----",width2+"-----"+measuredWidth2); } //11-28 17:03:17.559 15990-15990/com.yc.cn.ycbanner E/1MainActivity-----: 0-----0 //11-28 17:03:17.567 15990-15990/com.yc.cn.ycbanner E/2MainActivity-----: 0-----760 //11-28 17:03:17.684 15990-15990/com.yc.cn.ycbanner E/3MainActivity-----: 960-----960 //11-28 17:03:17.685 15990-15990/com.yc.cn.ycbanner E/4MainActivity-----: 960-----960
什么时候测量宽高不等于实际宽高?
MeasuredWidth/height!=getWidth/Height()的场景:更改View的布局参数并进行重新布局后,就会导致测量宽高!=实际宽高
3.0.0.6 平时写的自定义控件有哪些?如何优化自定义view?View的绘制流程说一下?自定义View的注意点?
平时写的自定义控件有哪些?
1组合控件。这种自定义控件不需要我们自己绘制,而是使用原生控件组合成的新控件。如标题栏,recyclerView封装控件。
2继承原有的控件。这种自定义控件在原生控件提供的方法外,可以自己添加一些方法。比如图片缩放控件,进度条控件。
3完全自定义控件:这个View上所展现的内容全部都是我们自己绘制出来的。比如百分比进度条控件
如何优化自定义 view
为了加速你的view,对于频繁调用的方法,需要尽量减少不必要的代码。先从onDraw开始,需要特别注意不应该在这里做内存分配的事情,因为它会导致GC,从而导致卡顿。在初始化或者动画间隙期间做分配内存的动作。不要在动画正在执行的时候做内存分配的事情。
你还需要尽可能的减少onDraw被调用的次数,大多数时候导致onDraw都是因为调用了invalidate().因此请尽量减少调用invaildate()的次数。如果可能的话,尽量调用含有4个参数的invalidate()方法而不是没有参数的invalidate()。没有参数的invalidate会强制重绘整个view。技术博客大总结
另外一个非常耗时的操作是请求layout。任何时候执行requestLayout(),会使得Android UI系统去遍历整个View的层级来计算出每一个view的大小。如果找到有冲突的值,它会需要重新计算好几次。另外需要尽量保持View的层级是扁平化的,这样对提高效率很有帮助。
如果你有一个复杂的UI,你应该考虑写一个自定义的ViewGroup来执行他的layout操作。与内置的view不同,自定义的view可以使得程序仅仅测量这一部分,这避免了遍历整个view的层级结构来计算大小。这个PieChart 例子展示了如何继承ViewGroup作为自定义view的一部分。PieChart 有子views,但是它从来不测量它们。而是根据他自身的layout法则,直接设置它们的大小。
View的绘制流程说一下?
View的绘制流程:OnMeasure()——>OnLayout()——>OnDraw()
第一步:OnMeasure():测量视图大小。从顶层父View到子View递归调用measure方法,measure方法又回调OnMeasure。
第二步:OnLayout():确定View位置,进行页面布局。从顶层父View向子View的递归调用view.layout方法的过程,即父View根据上一步measure子View所得到的布局大小和布局参数,将子View放在合适的位置上。
第三步:OnDraw():绘制视图。ViewRoot创建一个Canvas对象,然后调用OnDraw()。六个步骤:①、绘制视图的背景;②、保存画布的图层(Layer);③、绘制View的内容;④、绘制View子视图,如果没有就不用;⑤、还原图层(Layer);⑥、绘制滚动条。技术博客大总结
自定义View的注意点?
View需要支持wrap_content、padding
ViewGroup需要支持子View的margin和自身的padding
尽量不要在View中使用Handler,View已经有post系列方法
View如果有线程或者动画,需要及时停止(onDetachedFromWindow会在View被remove时调用)——避免内存泄露
View如果有滑动嵌套情形,需要处理好滑动冲突
3.0.0.7 View的wrap_content和match_parent效果一致的原因分析?getDefaultSize方法的处理逻辑?
View的wrap_content和match_parent效果一致的原因分析?
根据View的onMeasure方法中的getDefaultSize方法,我们可以发现在两种模式下,View的测量值等于该View的测量规格MeasureSpec中的尺寸。
View的MeasureSpec本质是由自身的LayoutParams和父容器的MeasureSpec决定的。
当View为wrap_content时,该View的模式为AT_MOST,且尺寸specSize为父容器的剩余空间大小。
当View为match_parent时,该View的模式跟随父容器的模式(AT_MOST/EXACTLY), 且尺寸specSize为父容器的剩余空间大小。
因此getDefaultSize中无论View是哪种模式,最终测量宽/高均等于尺寸specSize,因此两种属性效果是完全一样的(View的大小充满了父容器的剩余空间)技术博客大总结
除非给定View固定的宽/高,View的specSize才会等于该固定值。
getDefaultSize方法的处理逻辑?
getDefaultSize: 根据建议获取的最小宽高和测量规格,决定实际的测量宽高
UNSPECIFIED模式:测量宽高 = 建议的最小宽高
EXACTLY / AT_MOST模式:测量宽高 = specSize技术博客大总结
View的getDefaultSize源码要点(决定了View宽高的测量值)
UNSPECIFIED模式时,宽/高为第一个参数也就是getSuggestedMinimumWidth()获取的建议最小值
AT_MOST(wrap_content)和EXACTLY(match_parent/具体值dp等)这两个模式下,View宽高的测量值为当前View的MeasureSpec(测量规格)中指定的尺寸specsize
3.0.0.8 ViewGroup(抽象类)的measure流程?getChildMeasureSpec获取子元素MeasureSpec的要点?
ViewGroup(抽象类)的measure流程?
ViewGroup没有onMeasure方法,只定义了measureChildren方法(onMeasure根据不同布局难以统一)
measureChildren中遍历所有子元素并调用measureChild方法
measureChild方法中会获取子View的MeasureSpec(getChildMeasureSpec),然后调用子元素View的measure方法进行测量
getChildMeasureSpec获取子元素MeasureSpec的要点?
子View的MeasureSpec是根据自身的LayoutParams和父容器SpecMode生成
当子View的布局参数为wrap_content,且父容器模式为AT_MOST时,效果与子元素布局为match_parent是一样的。因此当子View的布局参数为wrap_content时,需要给指定默认的宽/高
LinearLayout的onMeasure()分析
ViewGroup因为布局的不同,无法统一onMeasure方法,具体内容根据布局的不同而不同,这里直接以LinearLayout进行分析
onMeasure会根据orientation选择measureVertical或者measureHorizontal进行测量
measureVertical本质是遍历子元素,并执行子元素的measure方法,并获得子元素的总高度以及子元素在竖直方向上的margin等。技术博客大总结
最终LinearLayout会测量自己的大小,在orientation的方向上,如果布局是match_parent或者具体数值,测量过程与View一致(高度为specSize);如果布局是wrap_content,高度是所有子元素高度总和,且不会超过父容器的剩余空间,最终高度需要考虑在竖直方向上的padding
3.0.0.9 View的layout过程?View的layout()源码分析?LinearLayout的onLayout方法?View的测量宽高和最终宽高有什么区别?
View的layout过程?
使用layout方法确定View本身的位置
layout中调用onLayout方法确定所有子View的位置
View的layout()源码分析?
调用setFrame()设置View四个定点位置(即初始化mLeft,mRight,mTop,mBottom的值)
之后调用onLayout确定子View位置,该方法类似于onMeasure,View和ViewGroup中均没有实现,具体实现与具体布局有关。
LinearLayout的onLayout方法?
根据orientation选择调用layoutVertical或者layoutHorizontal
layoutVertical中会遍历所有子元素并调用setChildFrame(里面直接调用子元素的layout方法)
层层传递下去完成了整个View树的layout过程
setChildFrame中的宽/高实际就是子元素的测量宽/高(getMeasure…后直接传入)
View的测量宽高和最终宽高有什么区别?技术博客大总结
等价于getMeasuredWidth和getWidth有什么区别
getWidth = mRight - mLeft,结合源码测量值和最终值是完全相等的。
区别在于:测量宽高形成于measure过程,最终宽高形成于layout过程(赋值时机不同)
也有可能导致两者不一致:强行重写View的layout方法,在传参方面改变最终宽/高(虽然这样毫无实际意义)
某些情况下,View需要多次measure才能确定自己的测量宽高,在前几次测量中等到的值可能有最终宽高不一致。但是最终结果上,测量宽高=最终宽高
3.0.1.0 draw的过程步骤是什么?View特殊方法setWillNotDraw是干什么用的?
draw的过程步骤是什么?
绘制背景(drawBackground(canvas))
绘制自己(onDraw)
绘制children(dispatchDraw)-遍历调用所有子View的draw方法
绘制装饰(如onDrawScollBars)
View特殊方法setWillNotDraw是干什么用的?
若一个View不绘制任何内容,需要将该标志置为true,系统会进行相应优化
默认View不开启该标志位技术博客大总结
默认ViewGroup开启该标志位
如果我们自定义控件继承自ViewGroup并且本身不进行绘制时,就可以开启该标志位
当该ViewGroup明确通过onDraw绘制内容时,就需要显式关闭WILL_NOT_DRAW标志位。
3.0.1.1 View中x,y,translationX,translationY分别是什么?View平移时是否改变了left、top等原始参数?
View中x,y,translationX,translationY分别是什么?
x,y是View当前左上角的坐标
translationX,translationY是在滑动/动画后,View当前位置和View最原始位置的距离。
因此得出等式:x(View左上角当前位置) = left(View左上角初始位置) + translationX(View左上角偏移的距离)
View平移时是否改变了left、top等原始参数?技术博客大总结
View平移时top、left等参数不变,改变的是x,y,tranlsationX和tranlsationY
3.0.1.2 MeasureSpec是什么?MeasureSpec的组成?测量模式SpecMode的类型和具体含义?MeasureSpec和LayoutParams的对应关系?
MeasureSpec是什么?
MeasureSpec是一种“测量规则”或者“测量说明书”,决定了View的测量过程
View的MeasureSpec会根据自身的LayoutParamse和父容器的MeasureSpec生成。
最终根据View的MeasureSpec测量出View的宽/高(测量时数据并非最终宽高)
MeasureSpec的组成?
MeasureSpec代表一个32位int值,高2位是SpecMode,低30位是SpecSize
SpecMode是指测量模式
SpecSize是指在某种测量模式下的大小
类MesaureSpec提供了用于SpecMode和SpecSize打包和解包的方法
测量模式SpecMode的类型和具体含义?技术博客大总结
UNSPECIFIED:父容器不对View有任何限制,一般用于系统内部
EXACTLY:精准模式,View的最终大小就是SpecSize指定的值(对应于LayoutParams的match_parent和具体的数值)
AT_MOST:最大值模式,大小不能大于父容器指定的值SpecSize(对应于wrap_content)
MeasureSpec和LayoutParams的对应关系?
View的MeasureSpec是需要通过自身的LayoutParams和父容器的MeasureSpec一起才能决定
DecorView(顶级View)是例外,其本身MeasureSpec由窗口尺寸和自身LayoutParams共同决定
MeasureSpec一旦确定,onMeasure中就可以确定View的测量宽/高
3.0.1.3 如何获取View的测量宽/高?如何在Activity启动时获得View的宽/高?Activity中获得View宽高的4种办法?
如何获取View的测量宽/高?
在measure完成后,可以通过getMeasuredWidth/Height()方法,就能获得View的测量宽高
在一定极端情况下,系统需要多次measure,因此得到的值可能不准确,最好的办法是在onLayout方法中获得测量宽/高或者最终宽/高
如何在Activity启动时获得View的宽/高?
Activity的生命周期与View的measure不是同步运行,因此在onCreate/onStart/onResume均无法正确得到
若在View没有测量好时,去获得宽高,会导致最终结果为0
有四种办法去正确获得宽高
Activity中获得View宽高的4种办法?技术博客大总结
onWindowFocusChanged
View已经初始化完毕,可以获得宽高;Activity得到焦点和失去焦点均会调用一次(频繁onResume和onPause会导致频繁调用)
view.post(runnable)
通过post将一个runnable投递到消息队列尾部;等到Looper调用次runnable时,View已经完成初始化
ViewTreeObserver
使用ViewTreeObserver的接口,可以在View树状态改变或者View树内部View的可见性改变时,onGlobalLayout会被回调;能正确获取View宽/高
view.measure
3.0.1.4 Activity启动到最终加载ViewRoot(执行三大流程)的流程是什么?
Activity启动到最终加载ViewRoot(执行三大流程)的流程是什么?
Activity调用startActivity方法,最终会调用ActivityThread的handleLaunchActivity方法
handleLaunchActivity会调用performLauchActivity方法(会调用Activity的onCreate,并完成DecorView的创建)和handleResumeActivity方法
handleResumeActivity方法会做四件事:performResumeActivity(调用activity的onResume方法)、getDecorView(获取DecorView)、getWindowManager(获取WindowManager)、WindowManager.addView(decor, 1)
WindowManager.addView(decor, 1)本质是调用WindowManagerGlobal的addView方法。其中主要做两件事:1、创建ViewRootImpl实例 2、root.setView(decor, ….)将DecorView作为参数添加到ViewRoot中,这样就将DecorView加载到了Window中
ViewRootImpl还有一个方法performTraveals方法,用于让ViewTree开始View的工作流程:其中会调用performMeasure/Layout/Draw()三个方法,分别对应于View的三大流程。
3.0.1.5 自定义View性能优化有哪些?针对异常销毁,自定义View如何优化?如何避免创建大量对象?
自定义View性能优化有哪些?
避免过度绘制
尽量减少或简化计算
避免创建大量对象造成频繁GC
禁止或避免I/O操作
onDraw中避免冗余代码、避免创建对象
复合View,要减少布局层级。
状态和恢复和保存
开启硬件加速
合理使用invalidate的参数版本。
减少冗余代码:不要使用Handler,因为已经有post系列方法.
使用的线程和动画,要在onDetachedFromWindow中进行清理工作。
要妥善处理滑动冲突。
避免过度绘制
像素点能画一次就不要多次绘制,以及绘制看不到的背景
开发者选项里内的工具,只对xml布局有效果,看不到自定义View的过度绘制,仍然需要注意。
尽量减少或简化计算
不要做无用计算。尽可能的复用计算结果。技术博客大总结
没有数据,或者数据较少的时候应如何处理,没有事件需要响应的时候如何处理。
应该避免在for或while循环中做计算。比如:去计算屏幕宽度等信息。
避免创建大量对象造成频繁GC
应该避免在for或while循环中new对象。这是减少内存占用量的有效方法。
禁止或避免I/O操作
I/O操作对性能损耗极大,不要在自定义View中做IO操作。
onDraw中避免冗余代码、避免创建对象
onDraw中禁止new对象.如:不应该在ondraw中创建Paint对象。Paint类提供了reset方法。可以在初始化View时创建对象。
要避免冗余代码,提高效率。
复合View,要减少布局层级。
复合控件:继承自现有的LinearLayout等ViewGroup,然后组合多个控件来实现效果。这种实现方法要注意减少布局层级,层级越高性能越差。
状态和恢复和保存
Activity还会因为内存不足或者旋转屏幕而导致重建Activity,自定义View也要去进行自我状态的保存和读取。
在onSaveInstanceState()保存状态;在onRestoreInstanceState()恢复状态
开启硬件加速
合理使用invalidate的参数版本。技术博客大总结
避免任何请款下之际调用默认参数的invalidate
调用有参数的invalidate进行局部和子View刷新,能够提高性能。
减少冗余代码:不要使用Handler,因为已经有post系列方法
View已经有post系列方法,没有必要重复去写。
可以直接使用,最终会投递到主线程的Handler中
使用的线程和动画,要在onDetachedFromWindow中进行清理工作。
View如果有线程或者动画,需要及时停止.
View的onDetachedFromWindow会在View被remove时调用,在该方法内进行终止
这样能避免内存泄露
要妥善处理滑动冲突。
View如果有滑动嵌套情形,需要处理好滑动冲突
关于其他内容介绍 01.关于博客汇总链接1.技术博客汇总
2.开源项目汇总
3.生活博客汇总
4.喜马拉雅音频汇总
5.其他汇总
02.关于我的博客我的个人站点:www.yczbj.org, www.ycbjie.cn
github:https://github.com/yangchong211
知乎:https://www.zhihu.com/people/...
简书:http://www.jianshu.com/u/b7b2...
csdn:http://my.csdn.net/m0_37700275
喜马拉雅听书:http://www.ximalaya.com/zhubo...
开源中国:https://my.oschina.net/zbj161...
泡在网上的日子:http://www.jcodecraeer.com/me...
邮箱:yangchong211@163.com
阿里云博客:https://yq.aliyun.com/users/a... 239.headeruserinfo.3.dT4bcV
segmentfault头条:https://segmentfault.com/u/xi...
掘金:https://juejin.im/user/593943...
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/72864.html
摘要:内部是调用效果是移动的内容,因此需要在的父控件中调用。和的情况相似,手机屏幕向下移动,为正值手机屏幕向上移动,为负值。 目录介绍 8.0.0.1 简述Android的事件分发机制?dispatchTouchEvent方法的作用是什么?说下View和ViewGroup分发事件? 8.0.0.2 onInterceptTouchEvent方法作用是什么?onTouchEvent的方法的作...
阅读 1351·2021-09-28 09:43
阅读 4123·2021-09-04 16:41
阅读 1919·2019-08-30 15:44
阅读 3731·2019-08-30 15:43
阅读 778·2019-08-30 14:21
阅读 2039·2019-08-30 11:00
阅读 3322·2019-08-29 16:20
阅读 1923·2019-08-29 14:21