转发请讲明出处


synchronized函数和synchronized代码块的界别


    1. 第一synchronized函数和synchronized代码快的效应范围有分别,synchronized函数一般锁定的是当下类对象,synchronized代码块锁定功能域可以选择是本对象,也足以是字符串等等.
    1. 此时此刻类对象锁没有自由的时候,本类的有所synchronized(this)同步代码块都打断。如若有并发请求synchronized函数,同一时间只可以有一个呼吁执行
      .
    1. 可是近来类对象锁没有自由的时候,其余请求可以访问本类中不带synchronized(this)的代码块,也得以访问非同一把锁的代码块例如synchronized(Str)等.
    1. 鉴于效果范围有分别,一般意义范围越小执行成效越高,常常支出中一般选用功能范围较小的synchronized.

哪些判定一个目的是足以被回收的


    1. 前边java虚拟机使用引用计数器的算法,当引用计数器为0时意味着该对象没有引用了解后被清理。可是那么些艺术很难化解循环引用问题,所以如今甘休使用了。
    1. 眼下利用的是可达性分析算法来规定一个对象是不是可以被回收。
    1. 原理是:通过一个叫GC
      Roots的目的当作根对象,然后起首向下搜寻,搜索的门路叫做引用链,当对象到GC
      Roots没有别的引用链相连的时候,则证实此目标是不可用的.
    1. 不可用对象并不是即时就推行回收措施,执行清理办法此前至少要经历三回标记进度.
  • ①如果目的在拓展可达性分析后发现并未与GC
    Roots相连接的引用链,那它将会被第三回标记并且举办三遍筛选,筛选的口径是此目的是不是有要求履行finalize()方法。当目的没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过,虚拟机将那三种情状都实属“没有要求履行”。(即表示一贯回收).

  • ②即使那些目的被判定为有须要履行finalize()方法,那么那几个目的将会停放在一个名为F-Queue的系列之中,并在稍后由一个由虚拟机自动建立的、低优先级的Finalizer线程去实施它。那里所谓的“执行”是指虚拟机会接触这些方法,但并不承诺会等待它运行截止,那样做的由来是,若是一个目的在finalize()方法中实践缓慢,或者发生了死循环(更极端的处境),将很可能会导致F-Queue队列中此外对象永久处于等候,甚至造成整个内存回收系统崩溃.
    1. finalize()方法是目标回收前的末段四回机遇,稍后GC将对F-Queue中的对象举行第二次小框框的标志,若是目的要在finalize()中不被回收,只要重新与引用链上的其余一个目标建立关系即可,譬如把自己(this关键字)赋值给某个类变量或者目标的成员变量,那在其次次标记时它将被移除出“即将回收”的联谊;假设目的那时候还一贯不避让,那大多它就真的被回收了。
    1. 其余一个对象的finalize()方法都只会被系统活动调用三遍,倘若目的面临下几遍回收,它的finalize()方法不会被另行实施,由此第二段代码的自救行动战败了。因为finalize()方法已经被虚拟机调用过,虚拟机都实属“没有要求履行”。(即表示从来回收).

写一个函数,输入一个数如38,拆分 3 + 8 = 11,1 + 1 = 2,最后2无法拆分就再次回到


    public  int  getNum(int num) {
        while (num >= 10) {
            num = num / 10 + num % 10;
        }
        return num;
    }

多少个经过同时调用一个ContentProvider的query获取数据,ContentPrvoider是何许反馈的啊?


  • 分析:
    咱俩精晓Activity那样的机件,它生命周期的回调函数是在UI线程中推行的,ContentProvider的onCreate()方法也是在UI线程中运行的,回答那些题材前,大家先是要搞清楚ContentProvider的Query(),insert(),delete(),updata()那多少个章程是否也是在UI线程中运作。
  • 意识题目:
    借使以上多少个艺术是在UI线程中运作的,那么三个线程并发去调用就很有可能出现ANR;固然不是在UI线程运行的,那它是在一个行事线程中运行的仍然在多个线程中运作的吧?即ContentProvider是否支持并发操作呢?
  • 解析问题:
    ContentResolver与ContentProvider类隐藏了得以完结细节,可是ContentProvider所提供的Query(),insert(),delete(),updata()那多少个主意都是在ContentProvider举办的线程池中运行的,而不是在经过的主线程中运作,以为这么些方法有可能被多少个地点调用,所以它们是线程安全的。
    ContentProvider完结进度通信是借助于Binder机制的,所以上述问题会回归到Binder线程处理问题,并不是每一个ContentProvider都会有一个线程池,而是一个进度共用一个线程池,共用的线程池就是Binder线程池。
  • 标准答案:
    一个content
    provider可以承受来自其余一个进度的数据请求。即便ContentResolver与ContentProvider类隐藏了得以完结细节,但是ContentProvider所提供的query(),insert(),delete(),update()都是在ContentProvider进度的线程池中被调用执行的,而不是经过的主线程中。那个线程池是有Binder成立和维护的,其实使用的就是各样应用进度中的Binder线程池。

Android设计ContentProvider的目标是何许?


    1. 躲藏数据的兑现格局,对外提供联合的数目访问接口;
    1. 更好的多寡访问权限管理。ContentProvider可以对开发的数据开展权力设置,差别的URI可以对应分化的权能,只有符合权限需要的零件才能访问到ContentProvider的具体操作。
    1. ContentProvider封装了跨进程共享的逻辑,我们只须求Uri即可访问数据。由系统来保管ContentProvider的创造、生命周期及走访的线程分配,简化大家在采取间共享数据(进程间通信)的主意。大家只管通过ContentResolver访问ContentProvider所提醒的数据接口,而不要求担心它所在进度是启动仍然未启动。

运作在主线程的ContentProvider为啥不会潜移默化主线程的UI操作?


    1. ContentProvider的onCreate()是运行在UI线程的,而query(),insert(),delete(),update()是运作在线程池中的工作线程的,所以调用那向个主意并不会卡住ContentProvider所在进度的主线程,但也许会阻塞调用者所在的进度的UI线程!
    1. 因而,调用ContentProvider的操作依然要放在子线程中去做。即使一贯的CRUD的操作是在办事线程的,但系统会让你的调用线程等待那么些异步的操作落成,你才足以继续线程从前的劳作。

请详细描述Android事件分发机制:


那道题是累累家面试集团会问到的一道经典面试题,但又平日被面试者忽略。

看了不少博客也看了成百上千代码,半数以上都是优柔寡断,不便民阅读固总括如下:

主线传递唯有三步:Activity->ViewGroup->View

Activity和View唯有多少个艺术控制事件传递:dispatchTouchEvent(),onTouchEvent
();

ViewGroup有三个方法控制传递:dispatchTouchEvent(),onInterceptTouchEvent(),onTouchEvent
();

接下去用一张图给大家讲述下实际是怎么一步一步分发的。

总结:
1.对于 dispatchTouchEvent,onTouchEvent,return
true
是终止事件传递。return false
是回溯到父View的onTouch伊芙(Eve)nt方法。
2.ViewGroup
想把温馨分发给自己的onTouch伊芙(Eve)nt,要求拦截器onInterceptTouch伊夫nt方法return
true 把事件拦截下来。
3.ViewGroup 的拦截器onInterceptTouch伊芙nt 默许是不阻拦的,所以return
super.onInterceptTouch伊芙(Eve)nt()=return false;
4.View
未曾拦截器,为了让View能够把事件分发给协调的onTouch伊芙(Eve)nt,View的dispatchTouch伊夫nt默许完成(super)就是把事件分发给自己的onTouch伊芙nt。

ViewGroup和View 的dispatchTouch伊夫(Eve)nt
是做事件分发,那么那个事件可能分发出去的三个对象
注:——> 后边代表事件目的必要肿么办。
1、 自己消费,终结传递。——->return true
2、 给自己的onTouch伊芙nt处理——->
调用super.dispatchTouch伊夫(Eve)nt()系统默许会去调用
onInterceptTouch伊夫(Eve)nt,在onInterceptTouch伊夫nt return
true就会去把事件分给自己的onTouch伊芙nt处理。
3、 传给子View——>调用super.dispatchTouch伊夫(Eve)nt()默许达成会去调用
onInterceptTouch伊芙nt 在onInterceptTouch伊夫(Eve)nt return
false,就会把事件传给子类。
4、
不传给子View,事件终止往下传递,事件伊始记念,从父View的onTouch伊夫(Eve)nt开始事件从下到上回归执行种种控件的onTouch伊芙nt——->return
false

注: 由于View没有子View所以不必要onInterceptTouch伊芙(Eve)nt
来控件是否把事件传递给子View仍然拦截,所以View的风云分发调用super.dispatchTouch伊芙nt()的时候默许把事件传给自己的onTouch伊芙(Eve)nt处理(相当于阻挡),相比较ViewGroup的dispatchTouch伊芙nt
事件分发,View的风浪分发唯有dispatchTouch伊夫(Eve)nt()和onTouch伊芙(Eve)nt()不必要onInterceptTouch伊芙nt()插手。

到此事件分发总计收尾。借使想详细询问事件分发机制的请看那篇博客:
http://blog.csdn.net/w525721508/article/details/78227154


View的渲染进程,或者叫View的绘图流程


那道题也是比较老的一道题了,可是无论BAT照旧小创业公司中冒出的功能相当高
接下去就计算性的讲述三遍View绘制流程,防止大书特书,接下去的讲述一切从简
但愿各位读者耐心看完,相信您会有很大的获取!
View绘图流程是在ViewRoot.java类的performTraversals()函数中举办的
绘制部分共计需求三步:

measure() -> layout() -> draw();

1. 判读是否再度统计视图大小(measure)

这边写图片描述

原理:从顶层父View像子View递归调用view.measure(),measure方法中回调onMeasure()
MeasureSpec是View的测量内部类,测量规格为int型,值由高2位规格形式specMode和低30位的具体尺寸specSize组成。

specMode有两种值

MeasureSpec.UPSPECIFIED :
父容器对于子容器没有任何限制,子容器想要多大就多大
MeasureSpec.EXACTLY:
父容器已经为子容器设置了尺寸,子容器应当坚守那一个边界,不论子容器想要多大的空中。
MeasureSpec.AT_MOST:子容器能够是宣称大小内的擅自大小

  • View的measure方法是final,不可以重载,只好重载inMeasure落成自己的测量逻辑

  • 顶层的DecorView的MeasureSpec是由ViewRootImpl中的getRootMeasureSpec方法确定(LayoutParams宽高参数均为MATCH_PARENT,specMode是EXACTLY,specSize为大体屏幕大小)。

  • ViewGroup类提供了measureChild,measureChild和measureChildWithMargins方法,简化了父子View的尺寸总结。

  • 若果是ViewGroup的子类就亟须必要LayoutParams继承子MarginLayoutParams,否则不可以利用layout_margin参数。

  • View的布局大小由父View和子View共同决定。

  • 选用View的getMeasuredWidth()和getMeasuredHeight()方法来获取View测量的宽高,必须确保那三个办法在onMeasure流程之后被调用才能回去有效值。

2. 是不是重新分配视图的地方(layout)

此处写图片描述

原理:
layout也是从顶层父View向子View的递归调用View.layout方法的历程,父View依照上一步measure子View得到的布局大小和布局参数,将子View放在合适的地方上。

  • View.layout方法可以被重载,ViewGroup.layout为final不得以被重载,ViewGroup.onLayout为abstract的子类必须重载落成团结的岗位逻辑

  • measure停止后得到的是各种View经测量后的measuredWidth和measuredHeight,Layout操作完未来得到的是各种View举行岗位分配后的mLeft,mTop、mRight、mBottom,这个值都是对峙父View

  • 凡是layout_XXX的布局属性都是对准父级View的,若是View没有父级容器则layout_XXX属性是绝非任何意义的

  • 利用View
    的getWidth()和getHright()方法赢得View测量的宽高非得确保那多个法子在在onLayout流程之后。

3. 是不是再次绘制(draw)

此地写图片描述

原理:
draw进程也是在ViewRootImpl的performTraversals()内部调运的,其调用顺序在measure()和layout()之后,那里的mView对于Actiity来说就是PhoneWindow.DecorView,ViewRootImpl中的代码会创设一个Canvas对象,然后调用View的draw()方法来推行实际的绘制工。所以又回归到了ViewGroup与View的树状递归draw进程

  • 假诺该View是一个ViewGroup,则需求递归绘制其所蕴藏的兼具子View。

  • View默许不绘制任何内容,真正的绘图都在和谐的子类中完结

  • View的绘图是借助onDraw()方法传入的Canvas类来拓展的

  • 不同View
    动画和ViewGroup动画,前者是View自身的动画可以透过setAnimation添加,后者能够由此xml布局的layoutAnimation属性添加

  • 在获得画布剪切区(每个View的draw中传唱的Canvas)时会自动处理掉padding,子View得到Canvas不用关爱这么些逻辑,只关注怎么样绘制即可

  • 默许情形下子View的ViewGroup.drawChild绘制顺序和子View被添加的一一一致,可是你也得以重载ViewGroup.getChildDrawingOrder()以提供差其余逐条

4. invalidate()

原理:
invalidate方法请求重绘View树(也就是draw方法),要是View大小没有暴发变化就不会调用layout进程,并且只绘制那么些“需求重绘的”View,也就是哪个View(View只绘制该View,ViewGroup绘制整个ViewGroup)请求invalidate体系措施,就绘制该View。

  • 一向调用invalidate方法.请求重新draw,但只会绘制调用者本身。

  • 触发setSelection方法。请求重新draw,但只会绘制调用者本身。

  • 触发setVisibility方法。
    当View可视状态在INVISIBLE转换VISIBLE时会直接调用invalidate方法,继而绘制该View。当View的可视状态在INVISIBLE\VISIBLE
    转换为GONE状态时会直接调用requestLayout和invalidate方法,同时鉴于View树大小暴发了变动,所以会呈请measure进度以及draw进度,同样只绘制需求“重新绘制”的视图。

  • 触发setEnabled方法。请求重新draw,但不会重复绘制任何View包蕴该调用者本身。

  • 触发requestFocus方法。请求View树的draw进度,只绘制“须要重绘”的View。

例:
当大家写一个Activity时,大家必将会由此setContentView方法将我们要显得的界面传入该办法,该方法会讲大家界面通过addView追加到id为content的一个FrameLayout(ViewGroup)中,然后addView方法中通过调运invalidate(true)去公告触发ViewRootImpl类的performTraversals()方法,至此递归绘制我们自定义的拥有布局。

5.requestLayout()

原理:
View的requestLayout时其实质就是偶发提升传递,直到ViewRootImpl为止,然后触发ViewRootImpl的requestLayout方法
requestLayout()方法会调用measure进度和layout进度,不会调用draw进度,也不会再也绘制任何View包蕴该调用者本身。

以上为View渲染的共同体进度,如有问题欢迎指正。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图