Android面试知识总结

Android知识

1.PathClassLoader和DexClassLoader的区别:

PathClassLoader的optimizedDirectory为null,所以只能去data/dalvik-cache目录加载dex,apk安装的时候,会把优化后的dex放在data/dalvik-cache的目录,所以PathClassLoader只能加载已经安装的apk

2.Acrivity启动流程

Activity生命周期onAttach-onCreate-onStart-onResume在一个主线程的消息处理中执行

3.插件化方案

插件Activity启动方案
1.hook Instrumentation重写startActivity方法和newActivity方法
2.hook AMS重写startActivity,替换H类
加载插件类的方案:
1.每个插件创建自己的ClassLoader
2.将插件的dex数组合并到宿主APP的dex数组中
3.自定义一个ClassLoader替换掉整个APP的ClassLoader
加载插件中资源的方案:
1.每个插件创建自己的AssertManager和Resource
2.将插件的资源路径添加到宿主App的AssertManager中,需要解决资源id冲突问题,可以修改aapt
资源id:packageId+TypeId+EntryId
packageId默认等于0x7f,不同的插件可以替换成不同的packageId比如0x11

4.android图片适配原则:

首先会在对应的目录中寻找,如果没有找到,接着在分辨率更高的目录查找,如果还没找到,在drawable-nodpi目录中查找,还没找到,去分辨率更低的目录查找,如果一个xxhdpi屏幕加载一个hdpi目录的图片。图片会被放大,反之则缩小,drawable-nodpi目录的图片不会被放大和缩小

5.AsyncTask:

默认会串行执行,可以手动改成并行执行,AsyncTask中线程池是static变量,所以一个进程中所有的AsyncTask都使用共同的线程池,减少资源开销
https://www.cnblogs.com/absfree/p/5357678.html
AsyncTask:
mWorker:WorkerRunnale类型实现Callable接口,call方法中调用doInBackground方法
mFuture:FutureTask类型,传入mWorker
SerialExecutor:实现Executor接口,调度任务,使之线性执行

FutureTask:
实现Runnable和Future接口,内部组合一个Callable用于执行任务
get方法回挂起调用线程,当任务执行完成时,唤醒调用线程,
内部在进行多线程操作时进行CAS(CompareAndSwap)判断

6.性能优化:

1.卡顿优化

  • 减少view树层级,工具:Hierarchy View,merge标签
  • 使用ViewStub,提高显示速度
  • 避免过度绘制,工具GPU过度绘制
  • 避免在主线程中进行耗时操作
  • 布局复用,比如ListView
  • 尽量使用LinearLayout替代RelativeLayout,减少测量次数,RelativeLayout会进行两次测量, FrameLayout如果为wrap_content,则会对match_parent的子View进行两次测量
  • 使用工具GPU渲染模式,查看渲染信息
  • 避免频繁大量的创建对象,减少GC频率

2.内存优化

  • 合理的使用软引用和弱引用,避免内存泄露
  • 合理的使用对象池,视图复用,Bitmap对象复用,减少内存开销
  • 使用最优的数据类型,比如SparseArray代替HashMap
  • Bitmap加载时使用simpleSize进行缩放后在加载

3.稳定性优化

  • 开发期间做好CodeReview
  • 使用静态代码扫描工具,lint
  • Crash监控与上报

4.网络优化:

  • 数据压缩GZip
  • 使用http缓存
  • http1.0,1.1,2.0
  • 网络状态:4G和Wifi下日志上报的策略发生改变

6.1:APP卡顿检测方案:

1.给主线程Handler添加日志输出类,检测dispatchMessage的执行时间
2.给Choreographer添加回调,如果两次回调的时间大于16ms,说明卡顿

6.2:DNS优化

传统DNS系统的缺点:
1.查询速度慢:显示本地DNS服务器,然后是根域名服务器,然后是顶级域名服务器
2.容易发生DNS劫持
使用HttpDns:
两种方案:

  • 在网络请求前,通过HttpDns查询ip地址,然后通过ip直连请求网络,并且将http header中的host设为原来的域名
    缺点:
    1.https证书验证,https证书验证是需要验证域名,可以通过hook相关方法,将ip替换回域名
    2.cookie或者keep-alive也需要适配
  • 重新定义网络的dns部分,替换为使用HttpDns查询ip,比如OkHttp就对外暴露了替换dns部分的接口

https://www.jianshu.com/p/b0c154215b48

7.Gradle:

Gradle生命周期
1.初始化:初始化阶段确定有哪些项目参与构建,并且为这些项目创建Project对象
2.配置:配置阶段执行每个项目的build文件
3.执行:执行构建task
Gradle构建的过程中可以添加hook函数,监听构建过程

gradlewrapper:可以保证在没有安装gradle或者gradle版本不兼容的机器上,快速下载安装gradle
classpath:使用在buildscript,用于表示构建时gradle自身所需要的资源,不会编译到最终apk中
implementation:表示打包过程中,我们的项目本身所要依赖的资源,会被打进最终的apk中
extention
Task
NamedDomainObjectContainer
https://blog.csdn.net/yanbober/article/details/65635040
https://blog.csdn.net/qq_28282317/article/details/79917547

8.SurfaceView与TextureView的区别

SurfaceView:
1.在自线程刷新View
2.看似的view树中,其实在WMS中作为一个独立的window,用有独立的Surface,所以不能进行平移旋转等操作
TextureView:
1.在子线程中刷新View
2.只能在开启硬件加速的窗口中使用
3.作为一个普通的View添加到View树中,可以平移旋转
SurfaceTexture:
1.可以将数据流转换成OpenGl使用的外部纹理,供TextureView或GLSurfaceView渲染

8.1:TextureView的使用场景:

1.小屏切大屏,或者跨页面的无缝衔接播放
https://www.jianshu.com/p/4e2916889f27

9.Handler

https://blog.csdn.net/wsq_tomato/article/details/80301851
发送消息的时候,会将Message的when属性设置为消息执行的时间戳,比如发送delay消息时,when等于当前时间戳加上delay,Message在加入消息队列的时候,会根据when属性,从小到大排序,小的先执行

9.1.Handler为什么不会阻塞主线程:

android应用程序在启动的时候,会在main方法中创建ActivityThread,并且为主线程创建Looper,进入消息循环,这样才不会导致主线程因为代码执行完毕而退出,activity的生命周期都是建立在主线程的消息循环上的,ApplicationThread在binder线程收到AMS的消息后,通过ActivityThread的H类给主线程的消息循环发送消息,执行相应的生命周期
当消息队列没有可执行消息时,线程会进入休眠状态,释放CPU资源,当有消息可执行时唤醒线程,阻塞时不会消耗大量CPU资源
https://www.zhihu.com/question/34652589

10.事件分发:

mFirstTouchTarget:保存消费该事件的子View
1.只有满足down事件或者mFirstTouchTarget !=null,才会调用onInterceptTouchEvent
2.如果onInterceptTouchEvent返回true,并且mFirstTouchTarget不为null,则将事件改为cancle事件传递给mFirstTouchTarget,并且将mFirstTouchTarget=null,则后面的事件不会在传递给mFirstTouchTarget,并且不会在调用onInterceptTouchEvent
https://www.jianshu.com/p/b85d2d85ff9d

11.RecyclerView分析:

RecyclerView:

1.measure过程:

measure过程分为3步,第一步dispatchLayout1:记录当前界面显示的View的上下左右四个位置
第二步dispatchLayout2:调用LayoutManager的onLayoutChildren,首先寻找锚点,然后一次向上和向下填充View,并且进行子View的measure和layout,在填充View的前后都会进行一次View回收
第三步dispatchLayout3:保存重新布局后的View的上下左右四个位置,然后执行动画,根据view的布局前后的坐标变化执行动画

2.滑动过程:

通过调用子view的offsetTopAndBottom实现View移动,移动之前通过fill方法填充新View和回收移出的view
通过scroller实现fling

3.view复用:

view复用分为4级:scrapped,cache,extensionCache,viewpool
scrapped:重新的layout时,recyclerView会先把界面上的view回收到scrappedview中,重新布局时复用,scrapped中的viewolder不需要重新绑定数据
cache:recyclerView在上下滑动的时候,会把滚出去的viewhodler添加到cache中,默认只保存两个,按position保存的,当再次进入的时候复用,不需要重新绑定数据
viewpool:cache中保存不下的view会回收到viewpool中,不同的Recyclerview可以使用同一个viewpool。复用时需要重新绑定数据
https://juejin.im/entry/586a12c5128fe10057037fba

12.EventBus

1.EventBus在进行注册的时候,会通过反射找到订阅事件的方法,并且保存在两个Map中,在收到消息时,直接在Map中查找即可,分别是1.subscriptionsBuyEventType,通过EventType查找订阅者和方法,2.typeBySubscriber,通过订阅着查找订阅事件
https://www.jianshu.com/p/83e44261e095

13.Activity异常时生命周期:

1.在onCreate中调用finish方法,会直接调用onDestory方法
2.系统配置发生变化时,比如横竖屏切换,会导致activity销毁重建,销毁时onStop之前回调onSaveInstanceState,重建时onStart之后回调onRestoreInstanceState
3.设置configChange属性,可以在系统配置发生变化时,禁止activity重建
4.内存不足时会导致优先级低的activity被杀死,并且回调onSaveInstanceState方法保存状态

14.Fragment:

1.Activity销毁重建的时候,FragmentManager自动重建之前的Fragment,所以在onCreate方法中创建Fragment之前应该先判断一下FragmentManager是否已经创建了该Fragment
2.Activity给Fragment传参的时候,应该使用setArgument方法,因为Activity在销毁的时候,会保存Fragment的状态以及对应的Argument,并且在重建的时候使用
3.操作Fragment的几个常见方法
1.add:将Fragment添加到容器,执行onAttach -> onResume
2.remove:add的逆过程中,onResume->onDetach,移除时如果加入退回栈,则只会销毁视图,即只回调到onDestoryView
3.replace:移除之前的Fragment,重新添加新的
4.detach:只是销毁视图,onPause,onStop,onDestoryView
5.attach:onCreateView,onActivityCreated,onStart,onResume
6.hiden:将fragment隐藏,不执行生命周期,回调onHiddenChange
7.show:不执行生命周期
https://www.jianshu.com/p/3d27ddc952fe

FragmentManager中mAdded 和 mActive的区别

mActive保存活着的fragment,添加fragment时保存到mActive中,调用onDetach后从mActive中移除
mAdded表示添加到FragmentManager中的fragment,添加fragment时添加到mAdded中,调用remove或者detach的时候,从mAdded中移除

14.1 懒加载

需要注意的点:
1.setUserVisibleHint为true
2.Fragment已经初始化完成
3.第一页Fragment调用setUserVisibleHint的时候,Fragment还没有初始化完成所以需要在onActivityCreate方法中在进行一次加载请求

14.2 fragment生命周期源码分析

1.在onCreate中添加fragment的生命周期
2.在onClick中添加fragment的生命周期
3.在ViewPager中的生命周期
https://www.jianshu.com/p/f2fcc670afd6

14.3 Fragment状态保存和恢复

http://www.androidchina.net/6317.html

15.FragmentPagerAdapter和FragmentStatePagerAdapter区别:

1.两个都会提前创建limit个Fragment
2.第一个Adapter在Fragment滑入的时候,会判断Fragment是否已经添加,如果没有则创建并且执行add,否则只执行attach,如果fragment移除limit需要销毁时,只执行detach销毁视图,Fragment实例并没有被销毁
3.第二个Adapter在划入时,先从缓存拿,如果有,直接返回,否则创建实例,并且执行add方法,在移除时,调用remove方法,清理缓存保存状态,状态在下次重建时使用
https://www.jianshu.com/p/6e7f894014b8

16.RelativeLayout与LinearLayout:

1.RelativeLayout会分别在水平方向和垂直方向各测量一次,LinearLayout在没有设置weight的时候进行一次测量,设置weight的时候,进行两次测量
2.优先使用LinearLayout,如果LinearLayout可能增加view层级或者需要使用weight,则使用RelativeLayout
https://www.jianshu.com/p/b9bd08ffe921

17.LeakCanary原理:

通过ActivityLifeCycleCallback监听activity生命周期,activity调用onDestory后创建一个activity的weak引用,并且关联一个引用队列,然后再子线程中判断引用队列是否有该weak引用,如果没有,则触发一个GC,在次判断引用队列中是否有该weak引用,如果有,则可能发生内存泄露,dump内存快照分析内存文件

18.属性动画原理:

属性动画开始的时候,会将自己作为callback添加到单利AnimationHandler中的一个List中,AnimationHandler有一个Choreographer.FrameCallBack的对象,choreographer收到垂直信号后,会回调这个对象的doframe方法,在这个方法中AnimationHandler会回调会有属性动画callback,属性动画会根据interpolator计算因子,并且根据差值器Evaluator计算出当前的变化值,进行动画
https://www.jianshu.com/p/d9deeffc1498

18.1View动画原理:

https://www.jianshu.com/p/48317612c164

19.加载Bitmap:

1.计算一张图片的大小:width * height * 4
2.设置了inSampleSize = 2,一张图片的大小:width / 2 * height / 2 * 4,所以在加载一张大图的时候,可以根据UI宽高,计算好inSampleSize
3.通过native加载一个Bitmap的时候,会传入图片坐在目录的density和屏幕密度targetDensity,native会计算缩放比例scale = targetDensity / density,然后加载图片。所以图片会被放大和缩小
4.实际图片所占内存大小:width * scale /sampleSize * height * scale / samplesize * 4
https://blog.csdn.net/jzman/article/details/88047730

20.Android多进程的优点:

1.分担主进程的内存压力,可以将一些比较耗费内存的模块放在一个独立的进程中
2.主进程和守护进程可以相互监视,有一方被杀重新启动它
缺点:
1.静态变量和单例全部失效:因为不同进程有独立的地址空间
2.线程同步机制完全失效
3.sp的可靠性下降:多进程读写文件,可能会出错
4.Application会多次创建
进程与线程的区别:
进程有自己独立的地址空间,一个进程崩溃后,不会对其进程产生影响,线程只是一个进程中的不同执行路径,线程有自己的堆栈和局部变量,但线程没有独立的地址空间,一个线程死掉,会导致整个进程死掉
https://blog.csdn.net/csdn_aiyang/article/details/69734557

21.ART与Dalvik区别:

dalvik是在每次运行时将dex文件转换成机器码,ART是在安装的时候将dex转换成机器码
ART的优点:
1.应用启动更快,运行更快,体验更流畅
2.更长电池续航能力
3.ART的性能高于dalvik
缺点:
1.安装速度慢
2.字节码转换成机器码后,占用的存储空间更大
https://www.jianshu.com/p/58f817d176b7

22.Serializable与Parcelable:

  1. serialVersionUID:只有serialVersionUID一致的时候,才能序列化成功
    2.静态成员变量属于类,不属于对象,所以不能被序列化
    3.transient修饰的变量,不能被序列化
    4.数据持久化选择Serializable,Intent传递优先使用Parcelable,Parcelable性能优于Serializable
    https://www.jianshu.com/p/2ed41bb7aa3a

23.AIDL:

AIDL用到的几个类:
1.IInterface:返回一个IBinder对象,表示可以进行binder通信
2.自己定义的接口类,继承自IInterface
3.Stub:继承自Binder,表示是一个Binder对象,可以进行跨进程调用,实现了自定义接口
4.Proxy:实现了自定义接口,Stub类的代理类
客户端通过ServiceConnection返回一个Bindler对象,因为不在同一个进程,所以客户端不能直接使用这个Bindler对象,通过这个Binder对象创建一个Proxy对象,可以通过使用Proxy对象,调用service服务
https://www.kancloud.cn/alex_wsc/android_plugin/480780

23.1:AIDL需要注意的问题:

1.AIDL的调用流程:
2.Binder死亡监听:DeathRecipient
3.Binder线程池:默认最多15个线程,可以修改
4.Client如果在主线程调用可能会ANR
5.权限验证:可以在onBinder验证,也可以在onTransact方法验证,在onTransact方法中可以进行包名验证

23.2:AIDL与Messager的区别:

1.AIDL支持面向对象调用,
2.AIDL支持高并发,Messager最终是将消息发给handler,线性处理
3.Messager使用简单
https://juejin.im/entry/589537b82f301e006904eb3e

23.3:Binder原理

https://blog.csdn.net/universus/article/details/6211589

24.Fresco分析:

可以将Fresco划分为3部分:
1.DraweeView:DraweeHierarchy,FadeDrawable,Drawable数组
2.Controller
3.ImagePipeline:ProduceSquence,MemoryCacheProduce,DecodeProduce,EncodeCacheProduce,DiskProduce,NetProduce还有分别对应的Consume
https://juejin.im/post/5a7568825188257a7a2d9ddb

25.OkHttp:

OkHttp通过一些拦截器对整个Http请求进行了封装,每个拦截器的处理过程分为:1.网络请求前处理,2.通过下层拦截器进行数据处理,3.网络请求后处理
主要的拦截器有:
RetryAndFollowUpInterceptor:重试和重定向拦截器,主要是在网络请求后,根据返回结果判断是否需要重新请求
BridgeInterceptor:1.在网络请求前往请求Header里面添加参数,比如ContentLength,ContentType,2.网络请求后,解析响应header里面的参数
CacheInterceptor:处理Http缓存逻辑,包括强制缓存max_age和对比缓存
ConnectInterceptor:进行socket链接
CallServerInterceptor:进行数据交换

为什么需要3个随机数
计算机中都是伪随机数,一个容易被猜出来,三个随机性更高一些
SPDY:
1.多路复用
2.请求优先级
3.header压缩
4.server推送
Http2.0:
Http2.0可以看成是SPDY的升级版
1.多路复用
2.header压缩
3.请求优先级
4.server推送
线程调度
Dispathcer:
如何连接socket
StreamAllocation,RealConnection,ConnectionPool,ConnectionIntercept,HttpCodec
如何缓存
CacheIntercept,CacheStrategy,CacheControl,DiskLruCache
https://www.jianshu.com/p/116ebf3034d9

25.1 http2.0与Okhttp

https://juejin.im/post/5c789dbce51d451ecc2028e7

26.Cookie:

Http是一种面向连接的无状态协议,也就是说,第一次请求和第二次请求之间没有任何联系,但是通常情况下,客户端在登陆完成后,后面的每次请求server应该知道客户端已经登陆,所以可以使用cookie来记录一些状态,登陆的时候,server响应消息的header里面添加set_cookie,客户端保存该cookie,下次请求的时候带上cookie,server便认为客户端已经登陆,可以使用CookieManager保存和获取cookie

27.加密:

非对称加密:公钥加密私钥解密,可以用于交换数据,私钥加密公钥解密,可以用于数字签名

CA机构:服务器可以将自己公钥在CA机构认证,CA机构生成一个包含该服务器公钥的签名证书,并且使用CA机构的私钥加密,客户端会保存一些CA机构公钥和信息,客户端收到签名证书后,通过CA的公钥解密,然后获取服务器的公钥

对称加密算法:DES,AES
非对称加密算法:RSA,DSA,ECC
签名算法:MD5,SHA1

28.Https:

Https = http + ssl,ssl位于应用层个传输层之间安全套接字层,提供了身份认证,数据加密和数据完整性校验,ssl的握手过程:
1.客户端向服务器say hello,并且发送自己所支持的加密算法,一个随机数
2.服务器向客户端say hello,从客户端支持加密算法中选择一个,一个随机数,服务器证书
3.客户端校验证书,获取服务器公钥,生成一个随机数,并且用公钥加密发给服务器,使用秘药生成算法和上面3个随机数,生成堆成加密的秘药
4.服务器使用私钥解密,同样使用3个随机数生成对称加密的密钥,并且告诉客户端握手完成
https抓包:主要手机安装并且信任抓包工具的证据,就可以抓https
https://juejin.im/post/5aeee624f265da0b8e7f4cdb

28.1:Https抓包和反抓包

CA证书的内容:
1.申请者公钥
2.申请者信息
3.有效期
4.CA机构签名
客户端在拿到证书以后,通过内置CA公钥解密签名,验证证书
https抓包:
charles作为中间人将自己证书替换为服务器的证书,发送给客户端,只要客户端信任这个证书,就可以通过验证,后续的通信都会被charles拦截
https反抓包:
1.客户端内置服务器证书,如果客户端判断服务器返回的证书和内置的不一样,则拒绝通信
缺点:证书到期后,需要将新的证书重新内置到APP中
2.客户端内置服务器的公钥:如果返回的证书中的公钥和内置的公钥不一样,则拒绝通信,只要服务器不更改私钥,公钥则一直有用
https://juejin.im/post/5c9cbf1df265da60f6731f0a

29.TCP:

三次握手是为了保证双方都可以发送数据和接受数据
四次挥手的状态变化,TIME_WAIT的目的
tcp是面向连接的,可靠的,基于数据流的传输层协议
udp是无连接的,不可靠的传输层协议
https://juejin.im/post/5ba895a06fb9a05ce95c5dac

30.MVC MVP MVVM:

结合自己项目,说说自己对代码架构划分的理解
在这里插入图片描述
https://www.cnblogs.com/wytiger/p/5305087.html

31.DataBinding原理:

1.DataBinding如何避免多次findViewById:
每次findViewById都会对View进行递归调用,找到对应的View,DataBinding在创建的时候,通过一次递归调用,将View保存在一个数组中,使用的时候,直接从数组中拿,避免了多次递归调用
2.DataBinding通过观察者模式,实现数据发生变化时更新View
https://blog.csdn.net/u012933743/article/details/78207447

32.APK签名:

Android APK签名是一种自签名,不需要CA认证,开发者使用私钥加密,应用程序安装时,使用公钥解密,并且对比摘要,只有校验通过,才能安装,因为不需要CA认证,所以其他人可以对APK进行重新签名
https://blog.csdn.net/itachi85/article/details/6564053

33.设计一个图片三级缓存框架:

https://juejin.im/post/5bca698751882576676f606a#heading-13

33.1: 自己实现一个图片加载框架:

异步图片加载框架

支持内存和磁盘缓存、支持按指定尺寸加载图片、支持从网络,文件,res目录加载图片、支持占位图和加载失败图
https://github.com/greekgoddess/BitmapLoader
Glide:
1.生命周期
2.内存缓存
3.磁盘缓存
4.BitmapPool

33.2:ImageView的ScaleType:

matrix
fit_xy
fit_start
fit_end
fit_center
center
center_crop
center_inside
https://www.jianshu.com/p/64790fce98e2

33.2: Glide源码分析:

https://www.cnblogs.com/guanmanman/p/7040942.html

34.view的measure,layout,draw过程:

1.measure:首先调用decorView的measure->onMeasure,在onMeasure中便利子View,调用子View的measure方法,decoreView的MeasureSpec是window的宽高和MATCH_PARENT,
2.layout:首先调用decoreView的layout->onLayout,在onLayout中便利子View,调用子View的layout方法,FrameLayout的onLayout方法会根据子view的gravity将子View放在一个合适的位置
3.draw:decorView的draw,在draw方法中分别调用drawBackground(如果全透明则不会调用),onDraw(如果全透明的则不会调用),dispatchDraw(绘制子view),drawForeground,
https://www.jianshu.com/p/48601578c9a8

34.1: view的工作流程measure,layout,onDraw

https://blog.csdn.net/qian520ao/article/details/78657084#commentBox

34.1.1:MeasureSpec:

1.若子View是具体的尺寸,则mode为EXACTLY,size为childSize
2.若子View是match_parent,则mode同父mode,size为parentSize
3.若子View是wrap_content,则mode为AS_MOST,size为parentSize,表示不可超过父size

34.2: android屏幕的刷新机制

https://www.jianshu.com/p/0d00cb85fdf3

34.2.1:什么是硬件加速

34.3: 自己实现一个ListView:

自定义View实现系统ListView功能
支持View复用,支持notifyDataSetChanged,支持滑动手势结束后继续滚动
https://github.com/greekgoddess/CustomListView

35.混淆

  • 代码混淆的好处:
    1.类名和包名都被重定义为无意义的命名,提高安全性
    2.删除无用类方法和变量
    3.优化字节码
  • 资源压缩:
    1.删除无用资源,减少包大小
    https://juejin.im/post/5d1717996fb9a07eeb13bc95

36.android打包流程:

1.使用aapt工具打包res资源,生成R文件
2.AIDL转化为java文件
3.编译java代码成class文件
4.使用dex命令,将class文件转换成dex文件
5.使用apkBuilder工具将资源还有dex文件打包成apk包
6.对apk包进行签名
7.通过zipalign对apk包进行对齐处理

36.1 资源打包的过程:

1.将文本类型的XML文件编译为2进制格式,并且有一个字符串常量池,保存xml标签,属性名,属性值等,减少体积大小
2.优化压缩Bitmap类型的资源
3.生成R文件
4.生成resources.arsc文件,该文件保存了资源ID和资源名称已经路径的表格
5.res/raw或者asset目录下的资源直接打包
http://zuoquanxiong.com/Android

36.2 class转换成dex:

class文件结构:

1.魔数
2.版本号
3.常量池
4.类信息(父类,接口)
5.字段信息
6.方法信息

Dex文件结构:

1.Header
2.string信息
3.proto方法原型信息
4.field_ids字段信息
5.method_ids方法信息
6.class_defs类信息
7.data数据区

dex相比class的优势:

1.体积更小,去掉了不同class之间冗余的信息
2.加载更快,避免了每次加载类都进行一次io操作,因为一个Dex文件包含了很多class
在这里插入图片描述
dex文件结构
class文件结构

37.onAttachedToWindow和onDetachedFromWindow

Activity在启动时,当DecoreView添加到WindowManager时会调用onAttachedToWindow,当Activity销毁时,decoreView从windowManager移除时,会回调onDetachedFromWindow,子View从父View移除时,也会回调onDetachedFromWindow
https://www.jianshu.com/p/e7b6fa788ae6

38.自己实现一个网络加载框架

网络请求框架

实现多线程异步网络请求、支持Http缓存、支持请求重定向、支持失败重试、支持GET,POST等常见Http请求、支持用户自定义返回数据类型
https://github.com/greekgoddess/NetworkFrame

39.自己实现一个资源下载器

支持多任务,多线程下载资源
https://github.com/greekgoddess/ResourceDownloder

40.线上OOM分析:

1.尽可能多的统计发生OOM时,用户操作的上下文,包括手机型号,内存大小,activity栈
2.分析用户操作上下文,寻找稳定的复现路径
3.dump内存文件,使用MAT分析内存文件

40.1.anr分析:

1.分析trace文件,trace文件会保存发生anr时的方法调用栈,进而找到发生anr的代码
2.使用BlockCanary检测主线程耗时

41:Android新版本适配

6.0:动态权限申请
7.0:

  • 系统广播删除:网络状态变更广播,拍照广播,录像广播,只有通过动态注册才能接收广播

  • 应用间共享文件限制:FileProvide

8.0:

  • 所有通知需要提供通知渠道
  • 取消隐式广播

9.0:禁止http请求网络
https://blog.csdn.net/weixin_38261570/article/details/81046352

42:WebView总结:

1.Android调Js:

  • loadUrl:
  • evaluateJavascript:4.4以上可用,效率高

2.Js调Android:

  • 通过addjavascriptInterface进行对象映射
    存在漏洞:
    4.2之前js可以中java对象上的任意方法
    4.2之后,google做了限制,只能执行@javascriptInterface注释的方法
    解决办法:
    4.2之前使用prompt,4.2之后可以使用addjavascriptInterface
  • shouldOverrideUrlLoading拦截url,scheme协议
  • 拦截alert,confirm,prompt消息

3.WebView漏洞:

  • addjavascriptInterface方法
  • 密码明文存储:询问用户是否保存密码弹窗
    解决办法: 关闭密码保存
  • file协议访问应用程序私有目录
    解决办法: 不用要访问文件系统的时候,禁止file协议,需要的时候禁止file协议加载js

4.WebView缓存和预加载:
缓存:

  • 浏览器缓存:也就是http协议缓存
  • AppCache:
  • Dom Storage:key-value,类似于SP,5M存储空间
  • DataBase缓存:
  • IndexedBase:也是Key-Value存储,是一种NoSQL数据库,可以存储复杂数据结构,4.4以上支持,取代DataBase

预加载:

  • 预加载WebView:可以在Application提前加载WebView,提高显示速度
  • 预加载H5:可以通过WebView提前加载H5,需要时直接addView即可
  • 自身构建缓存:通过重写WebViewClient的shouldInterceptRequest拦截H5的资源请求,进行缓存和读取

https://blog.csdn.net/carson_ho/article/details/71402764

Java知识:

1.重写equals时需要重新hashCode方法

2.SparseArray,ArrayMap

SparseArray:
时间换空间
优点:使用int代替Integer,内存占用少,
缺点:
1.使用二分查找法找到Key的index,相比于HashMap查找速度慢,不适合大量数据
2.添加新元素时,需要移动数组元素
扩容:2倍扩容,扩容时需要移动数组
HashMap:
扩容时需要对所有元素重新hash
位运算代替取模,提高性能,容量必须为2的次方
hash链表大于8个时,使用红黑树
ArrayMap:
保存两个数组,一个是hash数组,一个是key,value数组,查找时,对key的hash值进行二分查找,找到在hash数组中的index,然后对应key,value数组中取出值
扩容:为缓存容量为4和8的数组,优先使用缓存数组
hash冲突时,从找到的index开始,分别向两头遍历,找到正确的index
https://blog.csdn.net/zxt0601/article/details/78333328

3. CopyOnWriteArrayList:

1.对数组进行写操作时,先加锁然后对原始数组进行copy,并且对新数组进行修改操作后,将新数组设置为List的属性,读操作不进行加锁
2.存在弱一致性问题,也就是说,对list进行读操作时,如果其他线程进行了写操作,读出来可能仍然是旧的数据,
3.适用于多读少写的情况

4.多线程同步

volatile:

1.可见性
2.禁止指令重排续
3.volatile修饰引用类型:只能保证引用地址的可见性,不能保证引用对象元素的可见性

synchronized:

1.可见性
2.原子性
3.有序性:因为一次只有一个线程访问,所以可以保证有序性

为什么多线程操作可能出问题:

每个线程在执行的时候都有自己的工作内存,线程在使用一个变量的时候,会先把这个变量从主存复制到工作内存,使用完后,再从工作内存刷新主存,但是从工作内存刷新主存的时间是不可预期的,所以,有可能一个线程修改了变量,但是还没有刷新主存,另一个线程去读变量,就会读到旧的数据

什么是工作内存:

工作内存可以理解为CPU的高速缓存,因为CPU的运算速度远远高于内存的读写,使用高速缓存可以提高CPU效率

什么是可见性:

一个线程对变量的修改可以立刻刷新主存,并且通知其他线程缓存失效

synchronized如何保证可见性:

jvm规定
1.一个线程在对共享变量lock之前必须清空工作内存中的共享变量,从而在使用共享变量的时候,需要重新从主存读取
2.一个线程在对共享变量进行unlock的时候,必须刷新最新值到共享变量

volatile的使用场景:

1.单例模式
2.一个线程写,多个线程读

https://juejin.im/post/5b35af3151882574aa5f69c5

5.类加载的过程:

加载,验证,准备,解析,初始化
1.加载:加载二进制流到内存方法区,并且生成Class对象
2.验证:

  • 文件格式验证:是否已魔数开头,主次版本号是否在当前虚拟机范围内
  • 元数据验证:这个类的父类是否允许被继承(final类不允许被继承),这个类是否实现了父类或者接口中的所有抽象方法,类中是否出现不合理的重载
  • 字节码验证:保证语义的合理性,比如类型转换是否合法
  • 符号引用验证:校验通过符号引用能否找到对应的类,符号引用所指向的信息是否有访问权限(public, private)

3.准备:为static变量分配内存,并且设置默认值,在方法区中分配内存,常量的初始值就是代码中设置的值
4.解析:将符号引用转换成直接引用
5.初始化:调用类构造器,执行static块,为static变量设置代码中的默认值,静态代码块按顺序执行
https://www.cnblogs.com/linghu-java/p/8551360.html

设计模式:

单例模式:Choreographer
适配器模式:ListView
观察者模式:Adapter的notifySetDataChange
享元模式:MessagePool
Builder模式:AlertDialog
代理模式:AIDL
工厂模式:
原型模式:clone
迭代器模式
组合模式:ViewGroup和子View
装饰器模式:ContextWrapper
模版方法模式:Activity生命周期
备忘录模式:onSaveInstanceState
解释器模式:解析Manifest文件
责任链模式:触摸事件传递
策略模式:属性动画的Interpolator
https://xiangzhihong.blog.csdn.net/article/details/53857371
https://juejin.im/entry/5b4b35fe6fb9a04fb401546d

设计模式的6大原则:

1.单一职责原则
2.依赖倒置原则:依赖抽象,不依赖具体
3.开闭原则:拓展开放,修改关闭
4.里氏替换原则:在使用基类的地方可以修改为任意子类
5.接口隔离原则:将庞大臃肿的接口拆分为更小的接口
6.迪米特法则:一个对象对他对象有最少的了解

数据结构与算法

1.二叉树遍历:

二叉树遍历

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值