[if !supportLists]1. [endif]activity生命周期
oncreate-onstart-onresume-onpause-onstop-ondetyoy
[if !supportLists]2. [endif]service生命周期
service启动方式有两种,已知是托管start service方式进行启动,另已知是通过bindservice方式进行启动,不同的启动方式他们的生命周期是不一样的。
A.通过start service方式启动的service,生命周期是这样的,start service-oncreate-onstartconmon-ondestroy这种方式启动的话,需要注意以下几个问题。1.当我们通过start service被调用以后,多次在调用start service oncreate方法指挥被调用一次,onstartconmon方法会被多次调用,当我们调用stop service的时候,ondestroy就会被调用,从而销毁服务,2.当我们通过start service启动时候,通过intent传值,在onstartconmon方法中获取值的时候,一定要先判断intent是否为null,
B.通过bindservice方式进行绑定,这种方式绑定service,生命周期走法,bindservice,oncreate onbind unbind ondestroy bindservice这种方式进行启动service的好处是更加便利activity中操作service,比如加入service中有几个方法,a,b如果需要在activitie中调用,在需要在activity获取serviceconncation对象,通过servbiceconnecation或获取service中内部类的类对象,然后通过这个类对象就可以调用类中的方法,当然这个类需要继承binder对象、
[if !supportLists]3. [endif]activity的启动过程
App启动的过程有两种情况,第一张是从桌面launcher点击相应应用图标,第二种是在activity中过调用startactivity 来启动一个新的activity。我们创建一个新的项目,默认的根activity就会在上一个activity上面,而我们从桌面点击应用图标的时候,由于launcher本身也是一个应用,当我们点击图标的时候,系统就会调用startactivitySately 一般情况下,我们所启动的acytivity的相关信息都会保持在intent中,比如action category等等。我们在安装这个应用的时候,系统也会启动一个pack manager service的管理服务,这个管理服务会对Androidmanifest.xml文件进行解析,从而得到一个应用程序中的线管信息,比如service activity,broadcast等等,然后获得相关组件的信息,当我们点击应用图标的时候就会调用startactivitySately方法,而这个方法内部则是调用startactivity,儿start activity方法最终还是会调用start activity for result这个方法,而在start activityforresulu这个方法,因为startactvityforresult是有返回结果的,所以系统就直接给一个-1,就表示不要结果返回,erstartactivityforresult这个方法实际是通过instrunmentation类中的execstartactivity方法来启动activity,instrumentation这个类主要作用就是监控程序和系统之间的交互,而在这个execstartactivity方法中获取activitymanagerservice的代理对象,通过这个代理对象进行启动activity。启动就会调用checkstartactivityResult方法,如果说没有在配置清单中配置有这个组件,就会在这个方法中抛出异常,当然最会是调用的是,application。schedule launch activity来进行启动activity,而这个方法中通过获取的到一个activity client record对象,而这个activity client record对象通过含量的人来进行雄安锡的发送,系统内不会讲一个activity组件使用activity client record对象来进行描述,而activity client record对象中保持有一个loaderapk对象,通过这个对象调用含量的人launch activity来启动activity组件,而页面的生命周期方法也就是在这个方法中进行调用的。
[if !supportLists]4. [endif]broadcast注册方式与区别
Broadcast广播,注册方式主要有两种
第一种是静态注册,也可以成为常驻型广播,这种广播需要在Androidmanifest.xml中进行注册,这种方式注册的发广播,不受页面生命周期的影响,即使推出了页面。也可以收到广播,这种广播一般用于监听系统的事件,如开机启动,来电,去电,锁屏,由于这种注册的方式的广播是常驻型挂钩吧,所以会赞扬cpu的资源、
第二种是动态注册,而动态注册的话,是在代码中注册的,这种注册方式也叫非常驻型广播,受到生命周期的影响,推出页面后,就不会在收到广播,我们通常运行在更新UI方面,这种注册方式优先级较高,最后需要解绑,否则会内存泄露,=广播是分为有序广播和无需广播。
[if !supportLists]5. [endif]HTTP client与httpurlconnecation的区别
首先HTTP client和httpurlconnecation都支持https协议,都是以流的形式进行上传或者下周数据,也可以说是以流的形式进行数据的传世,还有ipv6以及连接池等功能,httpclient这个拥有非常多的apl,所有如果想要进行扩展的话,并且不破坏他的兼容性的话,很难进行扩展,也就是这个原因,Google在Android6.0的时候,直接弃用了HTTP client,而httpurlconnecation相对来说就是比较轻量级了,apl比较少,容易扩展,并且能够满足Android大部分的数据传输,比较经典的一个框架volley,在2.3版本以前都是使用httpclient,在2.3以后就使用了httpurlconnecation
[if !supportLists]6. [endif]Java虚拟机和dalvik的区别
Java虚拟机:
[if !supportLists]A. [endif]Java虚拟机基于栈,基于栈的机器必须使用指令来载入和操作栈上数据,所需指令更多很多
[if !supportLists]B. [endif]Java虚拟机运行的是Java字节码,Java类会被编译成成一个或者多个字节码。Class文件
Dalvik虚拟机
[if !supportLists]A. [endif]Dalvik虚拟机是基于寄存器的
[if !supportLists]B. [endif]Dalvik运行的是自定义的.dex字节码格式,Java类被编译成,class文件后,会通过一个dx工具讲所有的,class文件专场一个,dex文件,然后dalvik虚拟机就会从其中读取指令和数据
[if !supportLists]C. [endif]常量池已被修改为只使用32位的索引,以简化解释器
[if !supportLists]D. [endif]一个应用,一个虚拟器实力,一个进行(所有Android应用的现场都是对应一个Linux线程,都运行在自己的沙盒中,不同的应用在不同的进程中运行,每个Android dalvik应用陈旭都被赋予了一个独立的linux PID)
[if !supportLists]7. [endif]进行保活
当前业界的Android进行保活手段主要分为,黑,白,灰三种,其大致的实现思路如下,
[if !supportLists]A. [endif]黑色保活,不同app进行,用广播相互唤醒,包括利用系统提供的广播进行唤醒
[if !supportLists]B. [endif]白色保活,启动前台service
[if !supportLists]C. [endif]灰色保活,利用系统漏洞启动前台service
黑色保活:
所谓的黑色保活,就是利用不同的app进程是使用广播来进行相互唤醒,举三个比较常见的场景,
场景1,开机,网络切换,拍照,拍视频的时候,利用系统产生的广播唤醒service或app
场景2,接入第三方sdk也会唤醒相应的app进程,如微信sdk会唤醒微信,支付宝sdk会唤醒支付,由此去散发开去,就会直接出发了下面的场景3
场景3,加入你手机里装了支付宝,淘宝,天猫,uc等阿里系的app.那么你打开任意一个阿里系app后,有可能就顺便把其他阿里系的app给唤醒了,
白色保活。
白色保活手段非常简单,就是调用系统api启动一个前台service进行,这样在系统的通知栏生成一个notification,用来让用户知道有这样一个app在运行着,哪怕当前的app退到了后台,如下发的lbe和qq音乐这样
灰色保活
灰色保活,这样保活手机是应用范围最广泛,他是利用系统的漏洞来启动一个前台service进程,与普通的启动方式区别在于,它不会在系统通知栏出出现一个notification,看起来就如同运行这一个后台service进行一样,这样做带来的好处就是,用户无法察觉到你运行着一个前台进程,但你的进程优先级又高于普通后台进行的,那么如何利用系统的漏洞呢大致实现思路如下代码
思路一,api<18,启动前台service时直接传入new notification,
思路二,api>=18同时启动两个id相同的前台service,然后讲后启动的service做stop处理
熟悉Android系统的童鞋都知道,系统处于体验和性能上的考虑,app在推到后台时系统并不会真正的kill掉这个进程,而是将其缓存起来,打开的应用程序越多,后台换乘的进行也越多,在系统内存不足的情况下,系统开始一句资深的一套进程回收机制来判断要kill掉哪些进程,以腾出内存来共给需要的app,这套杀进程回收内存的机制就叫,low memory killer 他是基于Linux内核的oom killer 机制诞生
进程的重要性,划分五级
前台进程foreground process
可见进行visible process
服务进service process
后台进程background process
空进程empty process
了解完low memory killer在科普下 oom_adj ,生命是oom_adj?它是Linux内核分配给每个系统进程的一个值,代表进程的优先级,进程回收机制就是根据这个优先级来觉得十分进行回收,对于oom_adj的作用,只需要记住一下几点即可。1.进行的oom_adj越大,表示此进程优先级越低,越容易被杀掉回收,越小,表示进程的优先级越高,越不容易被杀掉回收,普通app进行的oom_adj=0系统的进程oom_adj才可能<0
有些手机就厂商把这些知名的app放入可自己的白名单中,保证了进行不死来提高用户体验,(如微信,qq默默都在小米的白名单中)。如果从白名单移除,他们终究还是个普通appp一样躲避不了被杀的命运,为了经理避免被杀,还是老老实实的去做好优化工作吧
所以,进程保活根本方案终究还是回到了性能优化上,进程永生不死终究是个彻头彻尾的伪命题
[if !supportLists]8. [endif]Context
Context是一个抽象基类,在翻译为上下文,可以理解为环境,是提供一些程序的运行环境基础信息,context下又两个子类,contextwapper是上下文功能的封装类,而contextimpl则是上下文功能的实现类,而contextwapper又又三个直接子类,contextthemewrapper。Service和application,其中,context'themewrapper 是一个呆主题的封装类,只有activity需要主题,service不需要主题,context一共又三种类型,分别是application,activity和service,这三个类型虽然承担这不同的作用,单塔恩都属于context的已知,而他们具体context的功能则是又contextimpl类去实现的,因此在绝大多数场景下,activity,service和application这三种类型的context都是可以通用的,不过有几种场景比较特殊,把比如启动activity,还有弹出dialog,处于安全原因的开了,Android是不允许activity或者dialog凭空出现的,一个activity的启动必须要简历在另一个acyivity基础之上,也就是以此形式的返回栈,而dialog则把必须在一个activity上面弹出,因为在这种场景下,我们只能使用activity类型的context,否则将会出错。
ge'ta'p'p'li'ca'ti'o'nContext和getApplication方法得到的对象都是同一个application对象,只是对象的类型不一样。
Context数量=activity数量+service数量+1(1为application)
[if !supportLists]9. [endif]理解activity view window三者关系
这个问题真的很不好回答,所以这里先来个算是比较恰当的比如形容下他们的关系吧
Activity像一个工匠(控制单元)window像窗户(承载模型),view像窗花,(显示试图)layoutinflayer像简单,xml配置像窗花图纸
[if !supportLists]A. [endif]activity构造的时候会初始化一个window,准确的说是phonewindow
[if !supportLists]B. [endif]这个phone window有一个viewroot 这个viweroot是一个view或者说是view group,是最初始的根视图
[if !supportLists]C. [endif]view root通过add view方法来一个个添加view,比如textview,button等
[if !supportLists]D. [endif]这些view的事件监听,是由window manager service来接受消息,并且回调activity函数,比如onclicklistener ,onkeyDown等
[if !supportLists]10. [endif]四种launchmode及其使用场景
[if !supportLists]A. [endif]队列先进先出,栈先进后出
[if !supportLists]B. [endif]对插入和删除的操作的限定,栈是限定只能在表的一端进行插入和删除的操作线性表,队列是限定只能在表的一端进行插入和另一端进行删除操作的线性表
[if !supportLists]C. [endif]遍历数据速度不同
Srandard模式
这个是默认模式,每次激活activity时都会创建一个新的activity实例,并放入任务栈最顶端,
singleTop模式
如果在任务的栈顶正好存在该activity的实例,就复用该实例(会调用实例的onNewintent())否则会创建一个新实例,使用场景如新闻类或者阅读类app的内容页
singleTask模式
如果过栈中已经有该activity实例,就会复用该实例(调用实例的onnewintent())复用时,会让该实例回到栈顶,因此在他上面的实例将会被移出栈,如果栈中不存在该实例,将会创建一个新的实例放入栈顶。
singleInstance模式
在一个新栈中光剑该activity实例,并让多个应用共享该栈中的activity实例,一旦该模式的activity已经存在某个栈中,任何应用在己合该activity时都会复用该栈中的实例,(调用onNewinent)其效果相当于多个应用共享一个应用,不管谁激活该activity都会进入同一个应用中,】
[if !supportLists]11. [endif]View的绘制流程
自定义控件:
[if !supportLists]A. [endif]组合控件,这个自定义控件不需要我们自己绘制,二十使用原生控件组合成的新控 件,如标题栏
[if !supportLists]B. [endif]击沉原有的控件,这种自定义控件提供原生控件方法外,还可以添加一些自己的方法,如制作圆角,原型图片等
[if !supportLists]C. [endif]完全自定义控件,这个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,6个步骤,1绘制试图的北京,2保持画布的试图layer,3绘制view的内容,4绘制view子视图,如果没有就不用,5还原试图layer,6绘制滚动条
[if !supportLists]12. [endif]View view group事件分发
[if !supportLists]A. [endif]Touch事件分发中只有俩哥哥主教,view group和view,view group包含,oninterceptTouchEvent,dispatch Touch Event,onTouchEvent,三个相关事件,view包含dispatchTouchevent,onTouchEvent两个相关事件,其中viewgroup又继承于view
[if !supportLists]B. [endif]view group和view组成了一个树状结构,根节点为activity内部包含的一个viewgroup
[if !supportLists]C. [endif]触摸事件有action_down,action_move,action_up组成,其中一次完整的触摸事件中,down和up都只有一个,move有若干个,可以为0个
[if !supportLists]D. [endif]当activity接受到touch事件时,将遍历子view进行down事件的分发,view group的遍历可以堪称时递归的,分发的目的时为了找到正真洋葱处理本次完整触摸事件的view,这个view会在touchuEvent结果返回true
[if !supportLists]E. [endif]当某个子view返回true时,会中止down事件的分发,同时view group中记录该子view,接下来的move和up事件将又该子view直接进行处理,由与子view时保持在view group中的,多层view group的阶段结构时,上级view group保持的会时真是处理事件的view所在的view group对象,如view group0-view group1-text view的结构,text view返回了true,它讲被保持在view group中,而view groupc。。。
[if !supportLists]13. [endif]保持activity状态
onsaveInstanceState会在activitiy转入后台状态之前调用,也就是onstop方法之间 ,onpause方法被调用后。
[if !supportLists]14. [endif]Android中几种动画
帧动画,指通过指定每一帧的图片和播放时间,有序的进行播放而形成动画效果,
补间动画,指通过指定view的初始状态,变化时间,方式,通过一系列算法进行图像变换,从而形成动画效果,主要有alpha,scale,tranlate,rotate,四种效果,注意,只是在试图层实现了动画效果,并没有真正改变view的属性,
属性动画,Android3.0的时候才支持,通过不断的改变view的属性,不断的重回而形成动画效果,相比于试图动画,view的属性时正在改变了,比如view的旋转,放大,缩小
[if !supportLists]15. [endif]Android中跨进程通讯的几种方式
Android跨进程通讯,像intent,content provider,service,都可以跨进程通信,
Intent这款跨进程方式并不是访问内存的形式,它需要传入一个uri,比如打电话
content provider这种形式,是使用数据共享的形式进行数据共享
Service远程服务 aidl
广播
[if !supportLists]16. [endif]aidl理解
Aidl。没一个进程都有自己的dalvik vm实例,都有自己的一块独立的内存,都在自己的内存上存储自己的数据,执行者自己的操作,都在自己的那片狭小的控件里过完自己的一生,而aidl就类似与两个进程之间的桥梁,使的两个进程之间可以进行数据的传递,跨进程通信有多种选择,比如broadcast receiver,messenger等,但是broadcast receiver占用系统资源比较多,如果事平凡的跨进程通信的话显然事不可取的,messenger进行跨进程通信时请求队列时同步进行的,无法并发执行。
Binder机制简单理解
在Android系统的binder机制中,是有client,service,servicemanager,binder,驱动程序组成的,其中,client,service,servicemanager 运行在用户空间,binder驱动程序是运行在内核空间的,而binder就是把这四种组件粘合在一块的粘合剂,其中核心的组件就是binder驱动程序,serve manage提供辅助管理的功能,而client和service正式binder驱动程序和service manager提供的基础设施上实现c/s之间的通信,其中binder驱动程序提供设备文件.dev.binder与用户空间进行交互
Client,service,servicemanager 通过open和ioctl文件操作相应的方法与binder驱动程序进行通信,而client和service之间的通信时通过binder驱动程序简介实现的,而binder manager时一个守护进程,用来管理service 并像client提供查询service接口的能力。
[if !supportLists]17. [endif]Handler的原理
Android中主线程时不能进行好事操作的,子线程时不能进行更新ui的,所以就有了handler,它的作用就是实现现场之间的通信。
Handler整个流程中,主要有四个对象,handler message,message queue,looper,当应用创建的时候,就会在主线程中创建handler对象
我们通过要传送的消息保持到message中,handler通过调用sendmessage方法讲message发送到message queue中,看ii烹饪对象就会不断的调用loop方法,不断从message queue中取出message交给handler进行处理,从而实现线程之间的通信。
[if !supportLists]18. [endif]Binder机制原理
在Android系统的binder机子中,时有client,service,servicemanager binder驱动程序组成的,其中client,service,servicemanager 运行在用户空间,binder驱动程序时运行在内核空间的,而binder就是把这四种组件粘合在一块的粘合剂,其中核心的组件就是binder驱动程序,servicemanager提供辅助管理的功能,而client和service正式在binder驱动程序和service manager提供的基础设施上实现C/S之间的通信,其中binder驱动程序提供设备文件/dev/dinger与用户控件进行交互,client,service,service manager通过open和ioctl文件操作相应的方法与binder驱动程序进行通信,而client和service之间的进程通信时通过binder驱动程序简介实现的,而binder manager时一个守护线程,用来管理service,并像client提供查询service接口的能力
[if !supportLists]19. [endif]热修复原理
我们知道Java虚拟机--jvm时价值类的class文件的,额Android虚拟机--dalvik/art/vm时价值类的dex文件的。
而他们价值类的时候都需要classloader,classloader有一个子类basedexcassLoader,而baseD'e'xClassLoader下有一个数据---DexPathList,用来存放dex文件,当baseDexClassLoader提供调用findclass方法时,实际上就是遍历数据,找到相应的dex文件,找到,则直接讲它return,而热修复的解决方法就是讲新dex添加到己合中,并且时在旧的dex的前台,所以就会有限被去除且return返回
[if !supportLists]20. [endif]Android内存泄露及管理
[if !supportLists]A. [endif]内存溢出oom和内存泄漏(对象无法被回收)的区别
[if !supportLists]B. [endif]引起内存泄漏的原因
[if !supportLists]C. [endif]内存泄漏检测工具leakcanary
内存溢出out of memory是指程序在申请内存时,没有足够的内存控件供其使用,出现out of memory。比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出了,内存溢出通俗的讲就是内存不够用
内存泄漏memory leak。是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏危害可以忽略,但内存泄漏堆积后果很严重,无论多少内存,迟早会被占光
内存泄漏原因
Handler引起的内存泄漏
解决讲handler什么为静态内部类,就不会持有外部类second activity的引用,其生命周期就和外部类无关了。
单例模式引起的内存泄漏
解决context是applicationContext,由于applicationContext生命周期是和app一致的,不会导致内存泄漏
非静态内部类创建静态实例引起的内存泄漏
解决,把内部类修改为静态的就可以避免内存泄漏了
非静态匿名内部引起的内存泄漏
解决,讲匿名内部类设置为静态的
5注册/反注册未成对使用引起的内存泄漏
解决注册广播,eventbus等 记得解绑
资源对象没有关闭引起的内存泄漏
在这些资源不适应的时候,记得调用相应的close destroy recycler release等方法释放
己合对象没有及时清理引起的内存泄漏
通常会把一些对象装入己合中,当不使用的时候一定要记得即使清理己合,让相关对象不在被引用
[if !supportLists]21. [endif]Fragment与 Fragment与activity通信的方式
[if !supportLists]A. [endif]直接在fragment中调用另外一个fragment中的方法
[if !supportLists]B. [endif]使用接口回调
[if !supportLists]C. [endif]使用广播
[if !supportLists]D. [endif]Fragment直接调用activity中的public方法
[if !supportLists]22. [endif]AndroidUI适配
字体使用sp使用dp,多使用match_parent,wrap_context.weight
图片资源,不同图片的分辨率,放在相应文件夹下可以使用百分比替代
[if !supportLists]23. [endif]App优化
App优化(工具 hierarchy viewer 分析布局工具 trace view测试分析耗时情况)
App启动优化
布局优化
相应优化
内存优化
电池优化
网络优化
App启动优化(针对冷启动)
App启动方式有三种
冷启动:app没有启动或app进程被killed,系统中不存在该app进程,此时启动app几位冷启动
热启动,热启动意味着你的app进程只是处于后台,系统只是将其从后台带到前台,栈是给用户,介于冷启动和热启动之间,一般来说在一下两种情况下发生
[if !supportLists]1. [endif]用户back退出了app,然后又启动,app进程可能还在运行,但是activity需要重建
[if !supportLists]2. [endif]用户退出app后,系统可能由于内存原因讲app杀死,进程和activity都需要重启,但是可以在oncreate中讲北大杀死锁保存的状态恢复、
优化:
Application的oncreate(特别时第三方sdk初始化),首屏activity的渲染都不要进行耗时操作,如果又,放在子线程或者intenservice中
布局优化:
经理不要过于复杂的嵌套,
响应优化:
Android系统每个16ms会发出VSYNC信号重绘我们的界面activity
页面卡顿的原因:
[if !supportLists]1. [endif]过于复杂的布局
[if !supportLists]2. [endif]UI线程的复杂运算
[if !supportLists]3. [endif]频繁的GC,导致频繁的gc有两个原因,1内存抖动,即大量的对象被创建又在短时间内马上被释放,2瞬间产生大量的对象会严重占中内存区域
电池使用优化(batterystats bugreport)
[if !supportLists]1. [endif]优化网络请求
[if !supportLists]2. [endif]定位中使用GPS。记得及时关闭