文章目录

  • 一.生命周期相关
  • 二.其他杂项
    • 2.1、Activity四种启动模式
    • 2.2.SharedPreference在使用过程中有什么注意点?
    • 2.3 assets与res目录区别
  • 三、动画
  • 四.RecycleView相关
    • 4.1.RecyclerView的缓存机制
    • 4.2.RecycleView与listView异同点
    • 4.3.recyleView优化
  • 五.View体系
    • 1. view的事件分发机制
    • 2. Activity、Window、DecorView与ViewRoot之间的关系
    • 3.自定义view。
  • 六、系统启动流程
  • 七、handler相关
    • 1.1描述:
    • 1.2MessageQueue 的 next 也是一个死循环,为什么死循环不会卡死?
    • 1.3message如何插入和回收消息?
    • 1.4如何避免内存泄露。
    • 1.5 message如何实现的延时加载
  • 八、开发技能拓展
    • 1.AndroidX适配
    • 折叠屏
    • 暗黑模式
  • 九、屏幕适配
  • 十、性能优化
    • 1.ANR条件
    • 2.UI优化
    • 3.包体积优化
    • 4.内存泄漏
    • 5.启动优化
    • 6.稳定性优化
  • 十一、热修复、插件化
    • 1.热修复
    • 2.插件化
  • 十二、设计模式
  • 十三、jetpack组件库
    • 1、首先是实现MVVM的一套工具,也是最常见的。
    • 2、LifeCycle
    • 3.ViewModel
    • 4.LiveData
    • 5.DataBinding
    • 6、Navigation
    • 7、Room
    • 8、WorkManager
    • 9.Padding
  • 十四、构建与打包能力
  • 十五、进程保活
  • 十六、安全
  • 十七、弱网优化
  • 十八、网络
    • 1. https数据传输流程
    • 2.http三次握手与四次挥手过程
    • 3.restful四种请求的区别
    • 4.http响应码
    • 5.http、https、tls、ssl联系
    • 6.socket、http、websocket、TCP、UDP联系
  • 十九、数据结构
  • 二十、一句话数据结构
    • 1.ArrayList
    • 2.LinkList
    • 3.hashset
    • 4.LinkhashMap
    • 5.treeMap
    • 6.线程安全的map
    • 7.线程安全的List
  • 二十一、直播
  • 二十二、管理
  • 二十三、算法
    • 二十四、源码分析
    • 1.Hander
    • 1.Arouter
    • 2.Glide
    • 3.ButterKinfe
    • 4.rxjava
    • 5.eventBus
    • 6. greendao
    • 7. mpchart
    • 8.retrofit
  • 二十五.binder机制
    • 1.1基本流程
    • 1.2.Client与ServiceManager都是用户空间,他们怎么调用?
    • 1.3 binder如何做到只复制一次的?
    • 1.4 多种夸进程方式为什么选择binder?
    • 1.5 Client与ServiceManager也是通过binder机制传输的?这不是鸡生蛋问题了吗?
  • 二十六.bundle机制
  • 二十七.线程与锁
    • 1.1 安卓多线程
    • 1.2java中的锁
    • 1.3线程池
    • 二十八、泛型
    • 二十九、注解
  • 三十、反射
    • 1.反射原理
  • 三十一、屏幕适配
    • 1.常见的屏幕适配方案
    • 2.AutoLayout原理
    • 3.今日头条屏幕适配
  • 三十二、协程

一.生命周期相关

 ##1.1 A activty跳转B activity走了哪些生命周期函数?A:pauseB:create Start resumeA:stop拓展:如果B的启动模式是sigletask/singleInstance且在任务栈中B:create start onNewIntent resumeA: stop
## 1.2 B finish关闭返回AB:pause A:restart start resumeB:stop destory拓展:如果A有监听onActivityResult呢?B:pause A:onActivityResult restart start resumeB:stop destory## 1.3 此时按下home键又返回A: stopA:restart start resume拓展:如果A上有FragmentFragment:pouse stopA:stopA:restart start Fragment:startA:resumeFragment:resume## 1.4 退出appA:stop destory## 1.5 A跳转B Activty,此时杀掉后台B:destory(只走最后可见的activity的destory方法)

二.其他杂项

2.1、Activity四种启动模式

 - statstand 默认- singTop  栈顶唯一,用于如新闻详情页,登录页面等不应该重复打开的场景- singTask 栈内唯一,有一个特点是调用时候会将这个activity的前面的Activity移除,一般用于首页。- singInstance 新任务栈,我们一般app内用的比较少,多用于打开第三方app,需要已新的任务栈的形式

2.2.SharedPreference在使用过程中有什么注意点?

commit()和apply()的区别

apply:  存内存、异步、无返回值。
commit: 存硬盘、同步、有返回值。

2.3 assets与res目录区别

assets不会自动生成ID,可以有子目录。
res会生成ID,并映射到R文件中。

三、动画

补间动画(对view矩阵进行变换,位置未改变)、属性动画(位置真正改变)、帧动画、自定义View实现动画
自定义估值器 : TypeEvaluator 接口,如ArgbEvaluator实现颜色渐变。
自定义差值器:实现速度变换(如先加速后减速)
贝塞尔曲线:实现路径的平滑变换(如加入购物车的抛物线轨迹)

四.RecycleView相关

4.1.RecyclerView的缓存机制

4.2.RecycleView与listView异同点

1. 缓存机制,recycleView四级缓存,listView两级,而且屏幕内缓存都是放在一个list中
2. ViewHolder 的编写规范化了不再需要像 ListView 那样自己调用 setTag
3. 支持多种布局LayoutManage内置了线性布局、网格布局、瀑布流布局
4. 更加方便添加item动画、控制滑动、修改Item分割线
5. recycleview不支持ItemClick,而是通过RecyclerView.OnItemTouchListener接口来探测触摸事件。虽然稍微
总体来说,recycleView在定义简单list时候会多写几行代码,但是其代码更简洁规范、功能也更强大。

4.3.recyleView优化

1. 如果 Item 高度固定,可以 setHasFixedSize(true) 来避免 requestLayout。如果不需要动画,也可以关闭默认动画。
2. 可以增加缓冲池大小
3. 局部刷新
4. 其他一些通用优化,如过度绘制、减少层级嵌套,数据分页,数据缓存
5. 有一个特殊场景是双列ListView或RecycleView不能使用weight,必须要写成固定值,否则将导致其频繁调用onmeasure造成卡顿。

五.View体系

1. view的事件分发机制

2. Activity、Window、DecorView与ViewRoot之间的关系

Activity*Activity不是真正展示页面的类。*Activity只负责生命周期和事件处理。*一个Activity包含一个Window,Window才是真正代表一个窗口。*更多的我们认为他是作为一个载体与入口的存在。PhoneWindow*Window才是真正代表一个窗口。*Window通过WindowManager加载了一个DecorView到Window中,并将DecorView交给了ViewRoot。DecorView*DecorView为整个Window界面的最顶层View(根节点)*DecorView 本身是一个 FrameLayout,是Android视图树的根节点视图,*包含了一个竖直方向的LinearLayout上面是ViewStub,延迟加载的视图(设置ActionBar),中间是标题栏TittleView(根据Theme是否显示),下面是内容栏ContentView(setContentView所设置的View)。ViewRoot*ViewRoot可以理解为DecorView与phoneWindow关联的工具类。*它比较重要的是View的三大流程measure layout draw都是通过ViewRoot完成。* Android所有的触屏事件、按键事件、界面刷新等事件都是通过ViewRoot进行分发的。WindowManage*WindowManager的 addView 方法把 DecorView 添加进去WMS(WindowManagerService) *AMS和WMS都属于Android中的系统服务*AMS统一调度所有应用程序的Activity*WMS控制所有Window的显示与隐藏以及要显示的位置

总结:Acitiviy不是真正的展示窗口,真正的展示窗口是PhoneWidow,一个Activity上面有一个PhoneWindow,一个PhoneWinow上有一个DecoView,DecoView上面的ContentView(R.id.content)才是我们真是写的布局文件所展示的位置,PhoneWindow通过WindowManager管理DecoView,ViewRoot 是 DecorView 的管理者,它负责 View 树的测量、布局、绘制,以及事件分发入口。WMS是PhoneWindow的管理者,是一个系统服务,管理window的显示隐藏以及要显示的位置。

3.自定义view。

View 的坐标系

#View 的坐标系统是相对于父控件而言的,已父控件左上角为原点:getTop()      //获取子 View  最上边  到父 View 顶部的距离getLeft()     //获取子 View  最左边  到父 View 左边的距离getBottom()   //获取子 View  最下方  到父 View 顶部的距离getRight()        //获取子 View  最右边  到父 View 左边的距离也就是说:getBottom() - getTop() = View 的高getRight() - getLeft() = View 的宽#MotionEvent 中的 getXxx 和 getRawXxx 的区别:
event.getX()    //触摸点相对于其所在父view中的坐标
event.getY()
event.getRawX() //触摸点相对于屏幕坐标系的坐标
event.getRawY()

MeasureSpec:

MeasureSpec 简单来说就是一个 int 值,高 2 位表示测量模式,低 30 位用来表示大小
EXACTLY: match_parent 和具体数值的情况
AT_MOST:wrap_content
UNSPECIFIED:表示不限定测量模式,父容器不对 View 做任何限制,这种适用于系统内部,我们一般不会使用

OnMeasure

*自定义View时候,测量的是自身大小
*自定义ViewGroup时候,还需要测试子View大小测量子view大小代码:measureChild(childview, widthMeasureSpec, heightMeasureSpec);测量自身大小代码:setMeasuredDimension(parentWidth,(heightMode == MeasureSpec.EXACTLY) ? parentHeight: parentautoHeight);
*padding自定义ViewGroup一般处理在OnMeasure中自定义View一般处理在onDraw中
*margin自定义ViewGroup,在onlayout中自定义实现自定义View不需要处理,是生效的

OnLayout

*遍历处理子view的位置(自己不需要),child.layout(l,t,r,b)
*也就是说,只有自定义ViewGroup时候才需要,如果没有子View可以不用复写。

OnDraw

*paint是画笔,可以设置颜色粗细这些
*canvas是画布,可以绘制点、线、圆形、方形等,还可以缩放、位移、旋转等k线实现主要就是通过canvas实现,基本原理是依次把线、蜡烛图、文字等绘制在canvas上,然后监听用户的手势及canvas的缩放平移等手段展示相应的k线图
*matrix是矩阵,canvas实践是通过matrix实现缩放、平移操作的底层实现。

RequesLayout与invalidate区别。

requestLayout是从新走measure-layout-draw流程
invalidate是从新走draw流程。


WMS与AMS有什么联系和区别?

AMS(ActivityManagerService)贯穿了Android系统组件的核心服务,
主要负责Android系统中四大组件的启动、切换、调度以及应用进程管理和调度工作。WMS(WindowManagerServeice)主要是管理窗口的,如管理窗口显示位置,尺寸,动画这些(分屏?)他们都是通过binder机制去传输的。

六、系统启动流程

当我们按下电源时,系统启动后会BootLoader层:加载引导程序Linux Kernel层:启动 Linux 内核,加载Linux驱动C++Framework层:启动 第一个用户进程:init 进程,启动adb进程,log进程,meadia服务然后孵化出第一个java进程:Zygote进程(承上启下,连接java与native存在)AndroidFramework层:通过SystemService.java启动AMS、WMS等所有的系统服务系统服务有一百多个,通过SystemServiceManager管理。Apps层:找到Launcher然后启动Launcher

七、handler相关

1.1描述:

首先通过 Handler 的 sendMessage 或 post 两种方式去发送消息,

post 内部也是 sendMessage 形式,只不过把传入的 Runnable 参数包装成 Message 的 callback。

然后把 Message 传给 MessageQueue 的 enqueueMessage 入队,

1.其实就是维护一个 Message 链表,它会根据 Message 的 when 时间排序,延迟消息不过是延时时间再加上当前时间。
2.我们都说looper是死循环,其实我看过messageQuqe源码,messageQuqe存消息和取消息都是一个死循环。
3.它实现Parcelable(安卓序列化方式,存内存)接口,实例化message建议使用obtain来实例化一个对象,因为obtain方法默认从message池中获取。

然后就是核心逻辑了,在 Looper 的 loop 方法,它是一个死循环,里面做了三件事,

一直调用 MessageQueue 的 next 方法取消息,然后再把消息分发出去。
然后通过 Message 的 target 去dispatchMessage 分发消息,
最后回收消息。

1.2MessageQueue 的 next 也是一个死循环,为什么死循环不会卡死?

这里就涉及到linux系统的管道机制(往管道里面写数据来唤醒cpu,采用nativeWake方法),
messageQuqe没有数据的时候cpu处于休眠状态(调用nativePollOnce),
只有消息到来的时候才会唤醒,所以不会占用大量cpu资源。附注:其实不止是Lopper是一个死循环,MessageQueue获取消息的时候也是死循环

1.3message如何插入和回收消息?

插入我们可以new,也可以用obtain方法从消息池中获取(推荐),
回收时候当message从messageQuqe中取走之后,就好调用回收方法,将message置空后放入消息池中。

1.4如何避免内存泄露。

1.如果需要持有activity变量的引用将其变为弱引用。
2.destory的时候移除handler的回调消息(mhandler.removeCallBackAndMessage(null))

1.5 message如何实现的延时加载

 所有的sendMessage方法都会调用sendMessageDelayed方法(只不过delayMillis=0),将消息发送到messageQuqe中的时候,会带着执行时间参数(当前时间+延迟时间),从消息队列取消息的时候先比较now和delayMillis的大小,now<delay,对延迟时间做一个差值,然后用差值延迟唤醒。

八、开发技能拓展

1.AndroidX适配

1.andoirdx=supportV4+supportV7
2.需要修改gradle.properties (
useAndroidX=true;//本项目使用AndroidX
enableJetifier=true//没有使用androidx的三方库使用Androidx适配
)
3.compileSdkVersion&targetVersion>28
4.gradle4.61 graldetool3.4.1
5.可以通过Androidstudio一键迁移(Refactor--Migrate to AndroidX)
6.有一些包一键迁移失败,需要手动修改

折叠屏

如果要适配折叠屏,第一步是把 resizeableActivity 设为 true,然后给 Activity 配置 configChanges,并进行测试。最后可以更近一步,给大屏幕设计另一套 UI,在折叠屏切换时切换 UI。

暗黑模式

1.自动适配

修改style.xml,打开forceDarkAllowed即可
原理颜色取反,简单但是效果差强人意。

2.自定义适配

建立light、night两套colors,颜色名称相同,色值不同。

3 结合换肤功能实现

可以使用Android-skin-support库实现换肤
基本原理,每个皮肤包一个model,加载不同皮肤下的颜色,资源文件

九、屏幕适配

十、性能优化

1.ANR条件

activity 5秒、BroadCastReciver 10秒、Service 20秒 未处理完事件。

2.UI优化

过度绘制、层级过深(<merge>)、重复执行

3.包体积优化

1.图片瘦身1.压缩png2.使用一个
2.资源文件瘦身1.删除无用资源2.字体优化3.so文件优化只保留armeabi一个文件夹so文件根据埋点动态下发3.代码瘦身主要移除一些不必要的sdk

4.内存泄漏

原因:长生命周期对象引用短生命周期对象常见的内存泄漏场景:1.toast不使用ApplicationContext2.定时器引用ActivityContext(或者UI组件如TextView这种)3.子线程(Handler/Thread等)引用ActivityContext4.mvp引发内存泄漏
通用解决方案:1.使用弱引用(WeakReference GC时候回收)2.生命周期结束的时候移除监听

5.启动优化

1.异步初始化(包含Application初始化数据及首页数据)
2.设置启用页图片主题(解决白屏问题)
3.首页数据缓存,优先展示缓存数据
4.子页面启动优化可以使用预加载,详情页可以直接使用列表页的数据展示,从网络获取数据成功后再更新。布局文件懒加载(Viewstub)

6.稳定性优化

 1.崩溃率:万分之5(5万月活)2.治理方案:1.编码阶段:代码评审、功能内审、统一容错处理。2.测试阶段:系统测试、兼容性测试。3.发布阶段:灰度发布。4.兜底方案:功能开关、热修复、强制升级,功能上线后观察崩溃日志,尽量都需要解决掉。

十一、热修复、插件化

1.热修复

1. 类加载方式(dex插桩)代表:微信Tinker、饿了么Amigo、QZone特点:下次启动生效,限制少,范围广原理:基于双亲委托机制原理,优先加载新的dex,当类加载器发现dex已经加载过了,就不会再请求了双亲委托机制(递归)1.加载一个class的时候先问父类有没有加载过,如果加载过,直接加载,一直到根节点BootstrapClassLoader2.从根节点向下询问是否可以加载,可以加载则直接加载
2.底层替换代表:阿里AndFix特点:立即生效限制多。

2.插件化

1、类加载静态代理:自己构造一个DexClassLoader,使用宿主contextHook:dex插桩,类似热修复
2、资源加载AssetManager获取插件中的asset资源hookResource中的资源
3、组件的生命周期Manifest预埋StubActivity,然后再hock

十二、设计模式

单例:分懒汉式(变量初始化)、饿汉式(双重加锁)天天用,比如初始化一个工具类
工厂模式:比如Fragment工厂
建造者模式:返回值是其本身,可以连点比如glide,以及我们自己实现的imageUtil
适配器模式:和回调函授有点类似。比如listview
观察者模式:用于消息通知比如RxJava、EventBus以及我们自己实现的长连接消息通知。
代理模式:我实现你的方法代替你去做某件事静态代理:开始的插件化框架(任玉刚Dynamic-load-apk)动态代理:retorfit这种用到注解的框架,可以用动态代理获取注解(但是有的注解比如ButterKinf、Arouter使用的是aspectJ字节码插桩生成修改后的java文件实现的)

十三、jetpack组件库

1、首先是实现MVVM的一套工具,也是最常见的。

mvvm = DataBinding+LiveData+ViewModel+LifeCycler
mvvm = DataBinding(xml解析)+LiveData(观察者)+ViewModel(数据存储)+LifeCycler(生命周期)

2、LifeCycle

观察者模式实现的生命周期感知组件。

3.ViewModel

数据存储组件,具备生命周期感知能力(集成Lifecycle能力)
ViewModel使用时候要手动实现观察者,一般直接使用LiveData


4.LiveData

数据订阅发布组件,具备生命周期感知能力(集成Lifecycle能力)
LiveData = 观察者+ViewModel+lifecycle

5.DataBinding

只是一种工具,用于解析xml中的数据写法。
基本原理是使用字节码插桩技术(Javassist,根据plugin生产java代码),
将xml布局文件中的内容解析为LiveData的代码(XXXbindingImpl)
达到简化书写,实现mvvm的目的

6、Navigation

单Activity架构,依赖xml配置,不利于组件化,国内一般使用Arouter

7、Room

orm框架,功能类似greenDao,用的比较少

8、WorkManager

后台任务组件,类似Service
相比service,它更轻量、简单、功能强大
(支持链式写法、任务队列、断网或重启app后还能继续执行)安卓8.0之后对service进行了限制
(要求后台服务变为5秒内前台通知)

9.Padding

一个分页组件,融合了LiveData,用处不大。

十四、构建与打包能力

1.自定义plugin(Javassist字节码插桩)

可以找到任意类任意方法添加代码
比如可以实现自动统计方法耗时。

2.app构建流程

十五、进程保活

开启前台service(推荐,缺点用户有感)
守护进程(失效)
开启1个像素的Activity(不推荐)
交叉唤醒(不推荐)
通过WorkManager定时任务保活(推荐)
通过长连接发送心跳保活(我们在用)

十六、安全

源码安全(混淆、加固、v2签名)
数据安全(传输加密、资源文件加密、缓存文件加密)
交互安全(界面劫持、反调试、输入监听、反截屏)
抗攻击行(组件导出风险、禁止root运行、webview非白名单体提醒)

加固原理

十七、弱网优化

1.数据优化a.数据压缩用protobuf代替json对数据进行Gzip压缩结合cdn,不同网络请求不同分辨率大小的图片b.数据缓存如首页、详情页,优先展示缓存数据一些配置文件可以内置在app中
2.界面优化a.页面先响应如点赞、收藏、评论等数据,可以页面先响应,数据后台发送可以结合WorkManager实现,重启后自动继续执行b.使用缓存数据展示比如淘宝首页京东商品详情页,先获取的是列表页的图片c.长连接数据,发送请求未及时响应提升网络连接慢,再长还没响应会提示重连d.一些界面给合理的loading,避免大白板或者展示错误数据
3.接口优化a.数据返回的慢服务端解决(可以redis缓存接口,cdn缓存文件)b.使用QUIC协议(也叫Http3.0,基于UDP实现)c.使用收费证书对ios影响比较大我们遇到过,链路追踪发现ios每次都会去校验证书,很多免费证书都在美国,速度影响很大

十八、网络

1. https数据传输流程

 1.https采用对称加密+非对称加密传输数据(非对称加密有性能问题)2.服务端通过非对称加密生成公钥发给客户端。3.客户端通过公钥对称加密数据与服务端进行连接。4.通过私钥解密公钥加密的内容

2.http三次握手与四次挥手过程

3.restful四种请求的区别

GET幂等:获取,如过去列表数据
POST非幂等:新建(提交),如注册用户
PUT幂等:更新,如修改密码
DEL幂等:删除
幂等:多次提交结果一致,也可以理解为多次提交修改的是同一条数据,是一种设计规范

get与post区别:

一般来说
get将参数放在URL中,POST将参数放在requestBody中
URL参数长度是有限制的(255),而body中没有。
get参数直接明文看上去似乎post请求稍微安全那么一丢丢。但是实际上没有本质区别
post请求也能将参数放在URL中,get请求也能将参数放在requestBody中,
其http请求本质都是tcp/ip协议。
但也有一些区别
GET请求会被浏览器主动cache,而post不会。
get与post在restful规范中的不同语义,一般我们也不会混用。

4.http响应码

1xx:不常用,表示接受到请求,需要继续操作,如请求收到了或正在进行处理。
2xx:表示成功,如200。
3xx:地址重定向,还需要进一步动作。如302。
4xx:表示客户端错误,如404。403权限被拒绝。
5xx:表示服务端错误,如503服务不可用,504网关超时。

5.http、https、tls、ssl联系

https=http+tls或ssl
tls1.0=ssl3.0
ssl3.0之后就不更新了,可以理解为tls就是新版本的ssl

6.socket、http、websocket、TCP、UDP联系

http和webSocket都是基于socket的应用层封装。
tcp是面向连接的,有三次握手过程。
udp是无连接的。一般传输音视频,但是现在好多直播协议比如rtmp也是用的tcp。

十九、数据结构

1.时间复杂度(根据遍历次数得出)

O(1):直接取/读,例如数组
O(logN)例如:二分查找法每次排除一半的可能
O(N):遍历一遍或有限几遍(常量次数):例如链表
O(N^2):循环套循环(例如2维数组)

2.数组

特点:内存连续并且按照顺序存储
时间复杂度:读O(1),写O(N)
举例:ArrayList(动态数组)扩容机制:1.5倍扩容,默认10扩容为整体复制,建议初始时指定长度

3.链表

特点:内存不连续,结构:value+指向下个节点的指针
时间复杂度:读O(N),写O(1)
举例:LinkList

4.二叉树

特点:二叉树是排序树,读写性能居中,位于数组和链表之间
时间复杂度:读/写O(logN)
举例:treeMapHashMap(数组+链表+红黑树)

5.HashMap原理
1.简单描述

数组+链表+红黑树
存储下标=hashcode%length。
相同位置的采用链表存储。存:简单说就是当我们put的时候,会先对key做hash后进行数组长度的取模运算,
得到一个存储下标位置,如果有下标相同的则以链表形式存储。
取:同样先获取到下标位置对应的链表,对链表进行遍历比对获取。
jdk1.7之后链表长度=8将链表换成了红黑树。已提高其查找性能。

2.Hash冲突

当我们对某个地址做hash地址运算时候,发现其地址以及被占用了,就会产生hash冲突,
hashmap的解决方案就是我们上面说的链地址法。
https://blog.csdn.net/xj80231314/article/details/88740628

3.扩容

当容量大于长度*0.75(初始为16,首次扩容即为12)时候,触发扩容(2倍)。
当链表长度达到8的时候链表转换为红黑树(提高查找效率)。
  1. 为什么负载因子是0.75?
    减少hash碰撞(太小了扩容频繁,太大了插入到后面hash冲突几率太大)

  2. 为什么初始化长度是16?
    太大了浪费空间,太小了扩容频繁
    6.扩容的性能损耗在哪?
    需要重新计算hash,重新插入一遍。

    https://blog.csdn.net/ye17186/article/details/88876417

二十、一句话数据结构

1.ArrayList

 动态数组、默认10,1.5倍扩容查询O(1),正常插入O(1),扩容的话需要整体复制

2.LinkList

 链表  查询O(N),插入O(1)

3.hashset

 底层:使用hashmap去重:先比较hash,再比较equals其他的hash也都用的气对应的map作为底层:如treeset使用的treeMap,linkHashSet使用的LinkHashMap.

4.LinkhashMap

 也是数组+链表+二叉树的结构,但是同时还加了一个链表来记录顺序。

5.treeMap

 数组+二叉树

6.线程安全的map

 ConCurrentMap(使用的renantranLock)HashTable(使用的Synchronized)

7.线程安全的List

CopyOnWriteArrayList(读写分离,写就直接复制)
vector(使用Synchronzied).

二十一、直播

采集 —>处理—>编码和封装—>推流到服务器—>服务器流分发—>播放器流播放

一、采集(获取音频或视频)二、处理(加水印美颜)三、编码(H264、H265、FFmpeg)
FFmpeg是一个工具,包含采集、编码、封装各个步骤四、封装(音视频合并)五、推流&拉流(RTMP、HLS、WebRTC)六、播放

二十二、管理

1.你在项目管理中做什么

1.任务分配与进度跟踪年初评估出整年的任务和工作量(公司规划和组内规划),将每个任务评估出初步详细的计划- 任务开始结束时间,提测时间,前者条件或风险点。- 指定重要节点的里程碑- 一些任务可能还需要我们出需求规格与设计文档根据年度任务分配每月任务到人-其实年度任务规划的时候也会分配到人,但是不准确按计划编码开发与提测。2.保证代码质量参与代码codeReview,功能内审,参与需求评审与设计评审。项目进度沟通与风险披露。3.统计日报与周报4.做项目架构相关ppt,向领导汇报

2.五大过程组

启动、规划、执行、监控、收尾过程组。

3.十大知识领域

项目整合、范围、时间、成本、质量、人力资源、沟通、风险、采购、干系人管理

4.三角模型

时间+成本+范围=质量

二十三、算法

二十四、源码分析

1.Hander

1.Arouter

Arouter是阿里提供的实现组件化的工具,支持全局降级和拦截器功能。
主要引用的四个包:
1.arouter-annotation开发阶段,定义了三种注解,分别为为参数、拦截器、路由页面
2.arouter-compiler编译阶段,处理注解的逻辑,arouter-compiler扫描使用注解的代码,并且通过javapoet将其转换为java代码(其原理类似于butterKinfe)
3.arouter-api运行阶段,真正的处理arouter的路由跳转的能力实现。首先会将所有的路由、拦截器、服务,分别存储到Warehouse类的Map中缓存。初次打开app的时候会扫描包下所有的className用于建立map的映射关系。然后会将映射关系存在sp中,下次打开就不会再扫描一遍了。
4. arouter-register(可选的,早期版本没有)运行加速阶段:上面提到Arouter会将映射关系存到sp中,这样依然有个问题是首次打开app依然会慢,arouter所以提供了arouter-resiger的gradle插件,通过gradle的transformer字节码插桩技术插入java的register代码,这样避免了首次打开时候的全文反射带来的性能损坏。附注:
1.JavaPoet、aspectJ、Javassist都是 用于注解生成java代码。
2.gradle字节码插桩也是个比较实用的技术,他可以实现比如全局埋点,代码耗时统计,大图片检查等。
像是我们常见的在gradle配置参数的也是这个原理实现的(比如配置bugly、友盟账号这些)

2.Glide

3.1.glide缓存机制(三级缓存)
弱引用缓存(内存WeakReference)--》-Lru算法缓存(内存)-》磁盘缓存(DiskLruCache)。
先从弱引用缓存中获取,有返回,没有从Lru中获取,有从Lru中移除放入弱引用中,没用从磁盘获取并放到LRU中,还没有从网络拉取。
内存获取会有一个引用计数,在图片加载完成后进行判断,如果引用计数为空则回收掉。(类似于垃圾回收机制)3.2glide没有内存泄露
glide与context的生命周期绑定,在Activity内部创建一个无UI的Fragment,
这个特殊fragment持有一个lifecycle引用,通过lifecycle将生命周期通知给glide,OnStart继续加载,OnStop暂停加载,OnDestory停止加载并清除任务。3.3.为什么使用了弱引用缓存
猜测,
1.内存占用问题,图片毕竟属于对内存占用较多的文件,优化内存是需要考虑的。
2.Lru算法效率并没有那么高

3.ButterKinfe

butterKinfe原理比较简单,和Arouter类型,扫描注解文件生成java代码(xxx_ViewBinding),自动生成findViewById这些代码。

4.rxjava

Rxjava 本质上是 观察者模式框架
被观察者将消息发送给全部的订阅观察者。

5.eventBus

eventBus是事件总线嘛,本质上其还是观察者模式。
register会把当前类中匹配的方法,存入一个map,而post会根据实参去map查找进行反射调用。https://blog.csdn.net/qq_38164867/article/details/81566641

6. greendao

greendao就是一个orm库, 他不是通过反射
GreenDAO框架一大特点就是通过在编译时生成辅助代码的方式,降低运行时的负担,提高运行时的效率。这里代码生成用的是FreeMarker。
在具体执行CRUD的时候,都是调用预先已经处理好的SQL语句进行拼接,并且还进行了优化(具体看TableStatements)

7. mpchart

mpChart是一个安卓图表工具,代码量不大,功能也不复杂。
基本原理就是view的绘图,和我们在view上绘制一个线段、一个图形其实是没有本质区别。

如何实现k线图的缩放、平移?

利用matrix矩阵,先一次性绘制,然后再再做缩放平移到指定位置。

常用关键类

ViewPort:作为一个中间类,里面维护了手势缩放、平移等操作的实际调用和限制。我们修改这个类来实现单次移动一个k线宽度、缩放基准点改为最左侧等手势相关信息。Transformer:是一个坐标转换类,实现屏幕坐标与线图点坐标的相互转换。我们用这个类实现长按手势定位到对应k线功能。render类(渲染器):    如XAxisRenderer ,是维护坐标轴线或者lable等数据及其格式的类。

我们修改源码时候一般使用静态代理方式(写一个子类继承要复写的类),将复写的方法写在子类中。

修改点:

单次移动一个k线宽度
缩放基准点改为最左侧
长按手势定位到最后一根
根据实时行情自动位移到最新位置
波段高低价
划线下单

https://www.jianshu.com/p/273840e9325c

8.retrofit

retrofit设计巧妙地方主要有两处。
1.是用了很多适配器模式,比如RxJavaCallAdapterFactory、GsonConvertFactory。做到了一个可插拔式的设计,后续可以很方便的替换掉第三方东西。

2.是使用了动态代理
代理模式:是当你在执行某个方法的时候,在这个方法前和方法后添加一些代码,然后继续执行该方法。
翻译到retrofit中就是当发起网络请求时候,我们通过反射获取到注解内容,将注解拼接到请求的方法中,然后再发起网络请求。
动态代理可以理解为java提供的一种特殊的写反射的方式。


参考:https://www.cnblogs.com/jacksontao/p/8552357.html

二十五.binder机制

1.1基本流程

Client:客户端,客户端。用户空间。
Server:服务端,服务端。需要向ServieManager注册服务。用户空间。
ServiceManager:用户空间。
Binder驱动:内核空间。比如我要给你发信件,我是Client,你是Service,我怎么找到你的地址?
需要你去ServiceManager(邮局)先注册一下,我发信的时候向邮局查一下你的地址,有就发出去,
Binder驱动就是用于实现中转的过程。

1.2.Client与ServiceManager都是用户空间,他们怎么调用?

通过binder驱动实现,
server注册过程:
告诉ServiceManager我是谁,我有什么,我能做什么。(比如我是金福林,我有一台电脑,他能开机)client执行过程:
首先Binder驱动将Service中的真实对象转换为代理对象返回给Client,Client拿到了代理对象,
调用代理对象的方法,通过binder驱动发送给Servicer进行逻辑处理工作,处理完毕后binder驱动将执行结果返回给Client。

1.3 binder如何做到只复制一次的?

事实上我上面的描述并没有体现出binder只复制一次,
Binder借助了内存映射的方法,在内核空间和接收方用户空间的数据缓存区之间做了一层内存映射,
就相当于直接拷贝到了接收方用户空间的数据缓存区,从而减少了一次数据拷贝接收方

1.4 多种夸进程方式为什么选择binder?

先说跨进程有什么?
socket,管道,共享内存。socket:用于网络传输的。服务端的微服务用socket连没问题,不适合本机传输,数据拷贝两次。管道:管道首先不适合传输大量数据,缓冲区设计的比较小,管道用于唤醒用的,
比如handler机制用到管道。那我们把缓冲区设计大一点是不是就行了?可以,但是他复制两次,而且有更好的方案。共享内存:故名思议,他无须数据复制,直接把共享缓冲区附加到用户空间上,但是他不安全。
那我们把他设计安全了是不是就行了,是的,binder机制就用到了共享内存的方式。

1.5 Client与ServiceManager也是通过binder机制传输的?这不是鸡生蛋问题了吗?

ServiceManager交互的binder机制比较特殊,他不需要名字就能连接,
或者说他的名字是固定的,就像是114查号,114是固定的类似ServiceManager,我是client,您是Server。

二十六.bundle机制

用处:Activity传递数据

1.1为什么实现了Parcelable接口?

Parcelable接口是存内存中的,效率更高。

1.2为什么使用ArrayMap?

ArrayMap是双数组存储,一个数组存排序好的hash值,一个数组存key-value的映射关系。查找key时候根据二分查找法查找对应的key。
数据量少,频繁

二十七.线程与锁

1.1 安卓多线程

1.2java中的锁

1.3线程池

二十八、泛型

二十九、注解

三十、反射

1.反射原理

 我们知道,java类会被编译成class文件,这些class对象会被classloader加载到内存中。反射原理是就是我们能够获取到class对象的引用,拿到此时这个class对象的私有化属性方法对我们都是透明的了。

三十一、屏幕适配

1.常见的屏幕适配方案

2.AutoLayout原理

遍历子控件,对每一个子控件的宽高根据比例修改。
缺点:
1.单位是px,侵入性强。
2.宽高都缩放,导致圆形或者正方形会看着变形。

3.今日头条屏幕适配

原理:我们无论使用任何尺寸单位(dp,sp)最终都会转换成px。
px = density * dp
density = dpi / 160
也就是我们转换px时候使用的density不使用系统的,而使用设计稿的。
density=当前设备屏幕总宽度(单位为像素)/ 设计图总宽度(单位为 dp)
项目:AndroidAutoSize

三十二、协程

kotlin协程使用的还是线程方式,它实际上是一个假协程,是一个类似与RxJava的实现方案,

一句话解决面试题--安卓篇相关推荐

  1. 软件测试知识点和面试题--手工测试篇(功能测试)

    软件测试知识点和面试题--接口测试篇 软件测试知识点和面试题--app测试篇 软件测试知识点和面试题--性能测试篇 如何熟悉项目 1.根据项目的UI界面和需求文档,使用思维导图整理项目的组织结构架构图 ...

  2. java iterator如何知道数量_Java开发岗面试题基础篇(二)

    点击蓝字 关注wo们 老哥们,接上篇<Java开发岗面试题--基础篇(一)>,本期推出Java开发岗面试题--基础篇(二),来看看Java中的集合.多线程.异常体系等知识在面试中是怎么体现 ...

  3. 详细前端面试题javascript篇--持续更新

    最新前端面试题汇总大全(超详细含vue,react,css,js,webpack,性能优化等)–持续更新点击查看 前端HTML篇 前端CSS篇 前端面试题js篇--持续更新 1. JS 数据类型 ?存 ...

  4. 大数据常见面试题 Hadoop篇(2)

    大数据常见面试题 Hadoop篇(1)_后季暖的博客-CSDN博客1)序列化和反序列化序列化就是把内存中的对象,转换成字节序列(或其他数据传输协议)以便于存储(持久化)和网络传输.反序列化就是将收到字 ...

  5. 大数据常见面试题 Hadoop篇(1)

    目录 1.描述一下hdfs的写流程 读流程? 2.详细讲解一下hdfs的体系结构 3.如果一个datanode出现宕机,恢复流程是什么样的? 4.通常你是如何解决Haddop的NameNode宕机的, ...

  6. Java面试题-进阶篇(2022.4最新汇总)

    Java面试题-进阶篇 1. 基础篇 1.1 基本数据类型和包装类 1.2 Double转Bigdecimal可能会出现哪些问题?怎么解决? 1.3 equals 与 == 的区别? 1.4 Java ...

  7. 大数据面试题_Hive篇

    文章目录 一.大数据面试题_Hive篇 (一)Hive表与性能优化 1.hive 内部表和外部表的区别 2. hive 有索引吗 3.sort by 和 order by 的区别 4.如何使用过 Hi ...

  8. android8手机 使用方法,技巧丨8条使用技巧, 让你手机更安全(安卓篇)!

    原标题:技巧丨8条使用技巧, 让你手机更安全(安卓篇)! 随着安卓手机用户越来越多, 安卓系统开源的特点,也引起了大众对手机安全的关注.今天,小编就为大家收集了安卓手机十大安全注意事项,希望能为你解疑 ...

  9. 1-Java面试题-基础篇

    Java面试题-基础篇 1.HashMap的底层实现? 1. map.put(k,v)实现原理:首先将k,v封装到Node对象当中;然后它的底层会调用K的hashCode()方法得出hash值;通过哈 ...

最新文章

  1. php判断字符串是否为IP,php 判断IP为有效IP地址的方法
  2. IE 市场份额暴跌,Edge 能否守住微软的辉煌
  3. 基于PYQT编写一个人脸识别软件
  4. MyBatis配置错误
  5. php 浏览器 兼容,兼容ie6浏览器的php下载文件代码分享
  6. .NET Core开发者的福音之玩转Redis的又一傻瓜式神器推荐
  7. from __future__ import absolute_import的作用
  8. JavaScript indexOf() 方法
  9. 数据仓库 和挖掘的步骤 - oracle
  10. 时间复杂度O(n^2)和O(nlog n)差距有多大?
  11. kali linux实体机_Linux基础命令——网络管理类
  12. JAVA自测题栏目正式上线,来测测你的Java功力到底如何!
  13. vc udp 广播接收和发送_udp聊天?使用udp+python实现多人聊天室
  14. 通过降低CPU频率 达到降低功耗的目的
  15. 如何将mov转换成mp4?详细的步骤分享
  16. MATLAB拟合函数使用说明
  17. Gartner 发布 2022 年人工智能技术成熟度曲线:复合 AI、决策智能快速发展,因果 AI 是热点
  18. 【音视频处理】码率、帧率越高越清晰?分辨率、像素、dpi之间是什么关系?码率的真实作用,I帧、B帧、P帧是什么
  19. 练习-Java输入输出之字节数据输入输出之综合练习
  20. 我只是还没有全力以赴

热门文章

  1. python词云图词频统计
  2. 让蒙娜丽莎活过来的视频驱动人像生成
  3. java 设置timezone_如何设置系统时区作为 @JsonFormat timezone
  4. the promise
  5. Charles使用技巧
  6. GitHub 用户排行榜
  7. OpenSubdiv--皮克斯演示开源图形技术
  8. 面试官问:MySQL误删表数据,如何快速恢复丢失的数据?
  9. opencv3.4.6 vs2017 win10 配置contrib库 教程
  10. 想兼职写作,要准备些什么?