
IntentFilter 为了匹配过滤列表,需要同时匹配action、data、category,否则匹配失败,acting、data、category可以有多个,只有一个intent同时匹配action、category与data类别才算完全匹配。data匹配规则:
scheme:URI模式,比如http、file、content,如果URI没有指定scheme那么整个URI其他参数无效。Host:URI主机名,比如www.google.com,如果host未指定,整个URI无效Port:端口号,比如80 只有当指定scheme与host,端口号才有意义。Android多进程模式下会造成以下几方面问题:
sharedprefrences的可靠性降低Application多次创建,当一个组件跑在一个新的进程中,系统由于要创建新的进程同时分配独立的虚拟机,这个过程就是启动一个新的应用过程,重新启动一遍,自然会创建新的Application。生成的Binder类
DESCRIPETOR:Binder唯一标识,一般用当前binder类名asInterface 将服务端binder对象转换成客户端所需的AIDL接口Stub对象本身,否则返回的是系统封装后的stub.proxy对象asBinder 用于返回当前binder对象onTransact 此方法运行在binder线程池中,当客户端发起跨进程请求时,远程请求经由系统底层封装后交由此方法进行处理,服务端通过code确定客户端请求目标是什么,接着从data中取出目标所需的参数,当目标方法执行完毕后,就向reply中写入返回值。onTransact 方法返回false,那么客户端请求失败。Binder 提供两个配对方法,linkDeath和unlinkDeath,通知linkDeath来设置死亡代理,当binder死亡时,重新发起连接从而恢复连接。Bundle 传递数据Messenger 是一个轻量级的IPC方案,它的底层实现了AIDL。支持一对多串行通信。支持实时通信。只能传输Bundle支持的数据类型。不支持RPC。AIDL,处理大量请求:service监听客户端请求,然后创建一个AIDL文件,将暴露给客户端的接口在这个AIDL文件中声明,最后在service中实现接口即可service,绑定成功后,将服务端返回的binder对象转换成AIDL接口所属类型就可以调用AIDL方法了Parcelable接口,通过RemoteCallbackList,它是系统专门提供删除跨进程listener接口的binder线程池中,同时客户端线程会被挂起,如果服务端方法比较耗时,就会造成客户端阻塞,如果客户端运行在UI线程,就会出现ANR。放在非UI线程即可ADIL中使用权限验证功能:
onBind中进行验证,验证不通过直接返回nullonTransact方法中进行验证,验证失败直接返回falseContentProvide,是用来不同应用之间可以数据共享。底层一样是binderonCreate()代表ContenProvider创建,一般做初始化操作,getType返回Uri请求所对应的MIME类型,如图片、视频等contentProvider通过Uri来区分外界访问的数据集合update、insert、delete方法会引起数据源改变,需要通过contentProvider的notifyChange通知外界数据发生改变,要观察contentProvider外界数据源已经发生改变,可以通过registerContentProvider注册观察者,与unregisterContentProvider解除观察者query、insert、delete、update四大方法存在多线程并发访问,需要进行线程同步,存在多个SQLiteDatabase需要进行同步因为对象之间无法进行线程同步,一个不需要线程同步,由于其内存对数据库操作有同步处理Socket实现进程间通信。不能在主线程中访问网络。可以通过网络传输字节流,支持一对多并发实时通信。不支持直接的RPCRPC 是什么
Remote Procedure Call (远程过程调 用) 是一种计算机通讯协议,它为我们定义了计算机 C 中的程序如何调用另外一台计算机 S 的程序,让程序员不需要操心底层网络协议,使得开发包括网络分布式多程序在内的应用程序更加容易。** Client/Server 模式,由客户端对服务器发出若干请求,服务器收到后根据客户端提供的参数进行操作,然后将执行结果返回给客户端。**TouchSlop:是系统所能识别出的被认为最小滑动距离,手指在屏幕上滑动,如果小于这个常量,就不认为进行滑动操作VelocityTracker:用于追踪手指在滑动过程中的速度GestureDecteor:手势检测,onDown手指轻轻触摸屏幕瞬间完成onShowPress 手指轻轻触摸屏幕,尚未松开或拖动onSingleTabUp 手指触摸屏幕后松开,这是单击行为onDoubleTap:双击,由两次连续的单击组成,不能与onSingleTabConfirmed共存onSingleTabConfirmed严格的单击行为,如果触发onSingleTabConfirmed,那么后面不能再跟一个单击行为Scroller:实现view的弹性滑动,实现过度效果。工作原理是:通过computeScroll让view不断进行重绘,根据重绘的时间间隔,得出view的当前滑动位置,根据位置通过scrollTo完成滑动,多次小幅度滑动就组成了弹性滑动了。scrollBy/scrollTo 实现view的滑动,只能将view的内容移动,不能将view的本身进行移动。滑动对比:
scrollBy/scrollTo 操作简单,适合view内容的滑动onInterceptTouchEvent,在内部做相应的拦截,首先ACTION_DOWN事件必须返回false,否则后续的ACTION_MOVE与ACTION_UP事件会直接交由父容器处理,无法传递给子元素。如果父容器ACTION_UP返回true,那么子元素的onclick事件无法触发。requestDisallowInterceptTouchEvent方法,当子元素调用parent.requestDisallowInterceptTouchEvent并设置为false,父容器才能拦截所需的事件,否则为true交由子控件处理。ViewRoot对应于ViewRootImpl类,它是连接windowmanager和DecorView的纽带,View的三大流程均是通过ViewRoot来完成的,在ActivityThread中,当activity创建完毕后,会将DecorView添加到window中,同时创建viewrootImpl对象,并将viewrootImpl与DecorView关联。View的绘制流程从viewRoot的performTraversals方法开始,经过三个过程将view绘制出来
measure过程决定了view的宽、高,measure完成后可以通过getMeasureWidth来获取view的测量后的宽与高,在几乎所有情况都是这样,特殊情况,Layout决定view的四个顶点,可以通过getTop,getBottom来获取view的四个顶点位置,通过getWidth获取view的最终宽高,只有draw方法完成后,view的内容才会显示在屏幕上
由源码可知,DecorView其实就是一个FrameLayout,view层事件都先经过DecoreView,然后在传递给view.
MeasureSpec 是view的内部类,他封装了view的规格尺寸,包括view的宽高信息,代表一个32位int值,高2位代表测量模式,低30位代表测量大小。
测量模式有三种:
UNSPECIFIED:父容器对view没有任何限制,view要多大有多大EXACTIY:父容器已经检测出view所需的精确大小,对应match_parent与具体数值AT_MOST:父容器指定了一个可用大小的specsize,view大小不能大于这个值,对应wrap_content.对于view其measurespec由父容器的measurespec与自身的LayoutParams共同决定的。measurespec一旦确定,就可以确定view的宽高。
如果父容器的measurespec为wrap_content,子元素的layoutparams为wrap_content与match_parent显示效果一样,需要在layoutparams为wrap_content指定默认的宽与高即可.
ViewGroup的measure过程:
viewgroup来说,除了完成自己的measure,还需遍历所有子元素的measure,和view不同,viewgroup是一个抽象类,没有重写view的onMeasure方法,提供了measureChildren方法。在某些极端得情况下,在onMeasure方法中拿到的宽与高可能不准确,在onLayout中获取宽与高才是最终的宽与高。
在activity启动时,获取view的宽高,在activity的生命周期中无法准确获取宽高,无法保证view测量完毕,获取宽高只能是0.
onWindowFocusChanged方法中获取,表示view已经初始化,onWindowFocusChanged会被调用多次,在activity窗口得到与失去焦点时都会被调用,继续执行,暂停执行也会,频繁进行onPause与onResume也会频繁调用。post将一个runnable投递到消息队列尾部
view.post(new Runnable(){ @Overribe public void run(){ int width = view.getMeasureWidth(); } })
viewTreeObserver众多回调可以获取宽高。使用onGlobalLayoutListener接口,当view树状态发生改变或者view内部可见性发生改变,它回调。measure得到view的宽高,比较复杂.wrap_content,必须对wrap_content做特殊处理,否则使用wrap_content就相当于使用match_parentpadding,直接继承自viewgroup控件需要在onMeasure与onLayout中考虑padding与margin对其造成的影响,不然导致padding与子元素的margin失效handler,使用post替代onDetachFromWindow中,不及时处理,可能会造成内存泄漏**直接继承view或viewgroup的控件,padding默认是不会生效的,需要自行处理。
view的requestLayout()绘制方式:
从源码注释可以看出,如果当前View在请求布局的时候,View树正在进行布局流程的话,该请求会延迟到布局流程完成后或者绘制流程完成且下一次布局发现的时候再执行。
子View调用requestLayout方法,会标记当前View及父容器,同时逐层向上提交,直到ViewRootImpl处理该事件,ViewRootImpl会调用三大流程,从measure开始,对于每一个含有标记位的view及其子View都会进行测量、布局、绘制。
该方法的调用会引起View树的重绘,常用于内部调用(比如 setVisiblity())或者需要刷新界面的时候,需要在主线程(即UI线程)中调用该方法。那么我们来分析一下它的实现
当子View调用了invalidate方法后,会为该View添加一个标记位,同时不断向父容器请求刷新,父容器通过计算得出自身需要重绘的区域,直到传递到ViewRootImpl中,最终触发performTraversals方法,进行开始View树重绘流程(只绘制需要重绘的视图)。
这个方法与invalidate方法的作用是一样的,都是使View树重绘,但两者的使用条件不同,postInvalidate是在非UI线程中调用,invalidate则是在UI线程中调用

一般来说,如果View确定自身不再适合当前区域,比如说它的LayoutParams发生了改变,需要父布局对其进行重新测量、布局、绘制这三个流程,往往使用requestLayout。而invalidate则是刷新当前View,使当前View进行重绘,不会进行测量、布局流程,因此如果View只需要重绘而不需要测量,布局的时候,使用invalidate方法往往比requestLayout方法更高效
它表示view的结构,可以在其他进程显示,提供一组跨进程更新界面。在Android中主要用来:通知栏与桌面小部件
它无法直接访问里面的view,必须通过所提供的方法来更新view,比如textview的setTextView方法。两个参数要设置的ID与提供的文本。
remoteviews使用了AppWidgetProvider类实现桌面小部件,本质是一个广播。
onEnable:当窗口小部件第一次添加到桌面时,调用这个方法,多次添加只会调用一次onUpdate:当小部件添加或每次更新都会调用方法,设置updatePeriodMillis指定更新周期onDelete:每删除一次都会调用onDisabled:最后一个该类型的桌面小部件被删除调用onReceive:广播内置方法,分发具体事件表示一种待定,等待,即将发生的意思。而Intent是立刻发生
**flags常见类型
FLAG_ONE_SHOT:只能使用一次,它会自动cancel,后续有,那么send会调用失败FLAG_NO_CREATE:当前描述的pendingintent不会主动创建,如果当前的pendingintent之前不存在,那么getActivity方法直接返回falseFLAG_CANCEL_CURRENT:如果当前的pendingintent已经存在,那么他们都会被cancel,系统会创建一个新的pendingintentFLAG_UPDATE_CURRENT:如果pendingintent已经存在,那么都会被更新。intent的Extras会被替换最新如果manager.notify(1,notification)第一个参数是常量,那么就会弹一个通知,后续通知会把前面完全替换掉,如果每次都不同,多次调用notify就会弹出多个通知.
系统没有通过Binder直接支持view的跨进程访问,而是提供了一个action概念,action代表一个view的操作,实现了Parcelable,首先将view的操作封装到这个action中,然后将对象跨进程传输传到远程中,接着在远程进程中执行action操作。应用每调用一次set方法,remoteViews就会添加一个对应的action,它的apply进行view的更新操作。remoteviews的apply方法内部会遍历所有action对象,并调用他们的apply方法,进行view的更新操作。
AppWidgetProvider的updateAppwidget内部通过apply与reapply加载更新界面
apply:加载布局并更新界面,而reapply只会更新界面。初始化会调用apply,后续调用reapply更新界面
remoteviews中的setOnclickPendingIntent只能给普通的view设置单击事件,不能给listview与stackview设置单击事件。要给它们设置单击事件,必须将setPendingIntentTemplate与setOnclickFillInIntent组合使用才行
它表示一种图像的概念,在开发中,被当做view的背景使用
一张图片所形成的的drawable,它的内部宽高就是图片的宽高,但一个颜色形成的drawable没有宽高,drawable内部宽高不等同于它的大小,drawable实际区域大小可以通过他的getBounds方法获取,一般与view的尺寸相同。它没有大小概念,当它被当做view的背景时,会被拉伸至view的同等大小。
BitmapDrawable:表示一张图片,通过xml方式描述它。
android:src 图片资源idandroid:antialias 抗锯齿android:dither 抖动效果 开启这个选项,让高质量图片在低质量的屏幕上还能保持较好的显示效果android:filther 开启过滤 当图片拉伸时,也能保持很好的显示效果android:mipMap 图像相关的处理技术 纹理映射 默认设置为falseandroid:tileMode 平铺模式 disable 表示关闭平铺模式repeat重复显示mirror 镜面显示 clamp图片四周元素会扩展到周围区域ShapeDrawable 通过颜色来构造图形,可以纯白,也可以渐变
android:shape:表示图片形状 rectangle oval(椭圆) ring 圆环其中line与ring要通过stroke标签指定颜色与宽度,否则无法显示corners 表示角度gradient表示渐变,与solid冲突solid 纯色填充stroke shape的描边padding 表示不是shape的空白,而是包含它的view的空白size标签设置的宽高就是shapedrawable的固有宽高
size 大小android:width 整型 宽度android:height 整型 高度LayerDrawable 表示一种层次化的drawable xml标签<layer-list>,将不同的drawable放置在不同的层上面达到一种叠加的效果
StateListDrawable:对应selector标签,表示Drawable集合,每个drawable对应一个状态。
android:constantSize:表示StateLIstDrawable固定大小是否不随着状态改变而改变,fasle表示改变**android:variablePadding:表示它的padding是否随着状态改变而改变,true表示改变**view的常见状态
android:state_pressed 表示按下android:state_focused表示获取焦点android:state_selected表示用户选择了view系统会根据view的当前状态从selector中选择对应的item,每个item对应一种drawable,从上往下查找,直至查找第一条匹配的item,将默认的item放在最后,不带任何状态。
LevelListDrawable:表示drawable集合,集合中每个drawable都有一个等级,最小等级0 最大等级10000 如果被当做Imageview,可以调用setImageLevel来切换。 等级范围 由maxLevel与minlevel
TransitionDrawable:对应transition标签,实现两个drawable之间淡入淡出效果
startTransition与reverseTransition实现淡入淡出已经逆过程InsertDrawable:对应insert标签,将其他drawable内嵌到自己中,当一个view希望自己的背景比自己实际区域小时,可以用这个样式。LayerDrawable也可以实现。
ScaleDrawable:对应标签<scale> ,根据等级来指定缩放比例
scaledrawable等级越大,那么内部drawable就看起来越大scaledrawable xml定义的缩放比例越大,那么内部drawable就看起来越小ClipDrawable:对应<clip>标签,根据当前等级来裁剪另一个drawable
clipOrientation表示裁剪方向,水平与竖直,gravity需要与clipOrientation一起才能有作用。等级为0表示裁剪全部区域,等级为10000表示不裁剪。Drawable 类有四个抽象方法子类必须实现:
public abstract void draw(Canvas canvas);
public abstract void setAlpha(@IntRange(from=0,to=255) int alpha);
public abstract void setColorFilter(ColorFilter colorFilter);
public abstract @PixelFormat.Opacity int getOpacity(); - draw:在 setBounds 方法设置的区域的 Canvas 中进行Drawable 的绘制,要绘制状态效果的话,可以由 setAlpha,setColorFilter 等方法控制;
setAlpha :给 Drawable 指定一个 alpha 值,在 0 - 255 之间;setColorFilter:设置滤镜效果,有时我们会在 Drawable 内部定义一个 Paint 对象,所以该方法的实现可以为 mPaint.setColorFilter(colorFilter);getOpacity :返回 Drawable 的透明度,取值为 PixelFormat.UNKNOWN,PixelFormat.TRANSLUCENT,PixelFormat.TRANSPARENT,PixelFormat.OPAQUE 中的一个;
public void setBounds(int left, int top, int right, int bottom); public void setBounds(@NonNull Rect bounds); protected void onBoundsChange(Rect bounds)setBounds 设置绘制区域矩形边界,draw 方法调用时会用到其设置的值,不设置默认边界均为 0,所以自定义 Drawable 时要重写该方法onBoundsChange setBounds 方法中新旧 bounds 发生变化时回调,默认为空方法;
public int getIntrinsicWidth(); public int getIntrinsicHeight();android:interpolator:插值器,会影响动画速度。android:shareInterpolator:集合中的动画是否和集合共享一个插值器android:fillAfter:表示动画结束后,是否停留在结束为止,true表示停留旋转动画放在位移动画之前,否则位移动画无法执行,组合动画执行顺序最好按照,缩放、位移、旋转与透明。
自定义view的方法并在需要的时候参考矩阵的变换细节,就可以写出特定的自定义view动画
帧动画使用简单,但较容易引起OOM,所以尽量避免使用过多尺寸较大的图片。
LayoutAnimation:作用于viewgroup,为viewgroup指定一个动画
属性:
android:delay 设置动画时间延迟android:animationOrder:动画顺序:normal ,reverse表示排在后面先开始,逆向,random随机动画**android:animation 具体的入场动画
overridePendingTransition(int enterAnim,int exitAnim)enterAnim被打开,所需动画资源exitAnim activity被暂停,动画资源属性动画要求动画作用的对象提供get和set方法,以动画效果多次调用set方法,每次传递set值不一样,随着时间推移,传递的值越接近于最终值。
针对上述问题:
view.clearAnimation清除动画View.isHardwareAccelerated()如果返回的是true,表示使用了硬件加速 Canvas.isHardwareAccelerated(),如果返回true表示这个图层开启了硬件加速