![](https://img-blog.csdnimg.cn/20190918140145169.png?x-oss-process=image/resize,m_fixed,h_224,w_224)
Android知识图谱
深入Android开发知识的方方面面,每篇文章读后都有所收获,是Android开发者不错的入门、进阶的知识图谱。
猴叻鳢
海阔凭鱼跃,天高任鸟飞
展开
-
Android事件分发及响应机制
若onTouchEvent返回true,则由当前View处理该点击事件,否则, 调用父View的onTouchEvent,尝试由父View响应处理。在自上而下进行事件派发的同时,下层子View并非只能被动接受事件派发,其可以通过设定 FLAG_DISALLOW_INTERCEPT 值,来反向制约上层View的拦截事件。返回值为true,则进入事件响应流程。事件响应流程与事件分发方向相反,即从子View到父View,直到事件被响应或事件被传递到根视图。若返回值为false,则进一步派发到子view中。原创 2024-03-14 10:36:52 · 456 阅读 · 0 评论 -
LinearLayout和RelativeLayout对比
3. RelativeLayout的子View如果高度和RelativeLayout不同,会导致RelativeLayout在onMeasure()方法中做横向测量时,纵向的测量结果尚未完成,只好暂时使用自己的高度传入子View系统。使用RelativeLayout时需注意上层的view可能不遮挡遮挡下层View的展示,但遮挡其点击事件。2. 实现复杂的UI布局,LinearLayout通常需要更多的布局层级。RelativeLayout的在复杂嵌套布局中,可以降低布局嵌套层级。原创 2024-03-14 10:21:43 · 687 阅读 · 0 评论 -
Android apk 打包及签名
alias meet:指定别名为meet,你同样可以自定义别名。-validity 10000:指定证书的有效期限为10000天。3. 执行gradle的assemble命令,完成打包及签名。-keysize 2048:指定密钥的长度为2048位。-genkey:指示keytool生成一个新的密钥对。-keyalg RSA:指定密钥算法为RSA。//Demo需要给同学们使用则暂不混淆。//是否启动ZipAlign压缩。-v:显示详细输出信息。:指定生成的Keystore文件名为。,你可以自定义文件名。原创 2024-03-13 15:57:48 · 562 阅读 · 0 评论 -
Android UI卡顿检测
mainLooperPrinter,并在mainLooperPrinter中判断start和end,来获取主线程dispatch该message的开始和结束时间,并判定该时间超过阈值为主线程卡慢发生,并dump出各种信息,提供开发者分析性能瓶颈。启动一个卡顿检测线程,该线程定期的向UI线程发送一条延迟消息,执行一个标志位加1的操作,如果规定时间内,标志位没有变化,则表示产生了卡顿。缺点:轮询不优雅,有不确定性,随机漏报。微信采用的即是该方案。优点:简单,稳定,结果论,可以监控到各种类型的卡顿。原创 2024-03-13 11:47:59 · 351 阅读 · 0 评论 -
Android的UI渲染机制(二)
当界面有变化或者主动调用invalidate申请重绘, 会首先标记当前UI需要重新绘制,但绘制不是同步的,只有当下一次vsync信号到来时, 才会执行measure/layout/draw开始绘制。由于每次都是在收到下一个vsync信号才开始绘制, 一旦上一帧出现jank, 由于backing_buffer还在占用, 下一帧的绘制会被延迟到下下一个vsync开始。实际上,我们可以另外再开辟一个buffer,替代被占用的backing_buffer,下一帧仍然在vsync到来时就开始绘制,这就是三缓冲策略。原创 2024-03-13 10:34:15 · 582 阅读 · 0 评论 -
Android的UI渲染机制(一)
当客户端 addView() 或者需要更新 View 时,会通过 SharedBufferClient写入数据到 ShareClient 中,SurfaceFlinger 中的 SharedBufferServer 接收到通知会将 FrameBuffer 中的数据传输到屏幕上。调用Activity的onCreate函数。ViewRoot是View视图体系的根,每一个Window(注意是Window,比如PhoneWindow)有一个ViewRoot,它的作用是处理layout和View视图体系的绘制工作。原创 2024-03-13 09:58:30 · 1003 阅读 · 0 评论 -
Android ArrayList、LinkedList 和 Vector 的区别
5.LinkedList提供了List接口没有提供的方法,方便数据的头尾操作。2.ArrayList扩容时按照50%增加,Vector按照100%增加。1.ArrayList非线程安全的,Vector是线程安全的。4.LinkedList是链表实现的,因此查询慢,增删快。3.ArrayList的性能要高于Vector。原创 2024-03-12 16:54:13 · 402 阅读 · 0 评论 -
Android垃圾回收机制
(3)新生代使用复制算法进行垃圾回收时,实际不是1:1分成两块,而是8:1:1分成eden、from、to三块。之所以有from、to两个小块,是因为部分对象可能在进入老生代前多次gc都不释放,那2次gc、3次gc就可以在from和to块中进行复制移动。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用的内存空间一次清理掉。从GC Roots作为起点,向下搜索它们引用的对象,生成一棵引用树,树的节点视为可达对象,反之视为不可达。虚拟机栈(帧栈中的本地变量表)中引用的对象。原创 2024-03-12 15:21:03 · 484 阅读 · 0 评论 -
Hash冲突常见解决方案
从发生冲突的那个单元起,按照一定的次序,从哈希表中找到一个空闲的单元。然后把发生冲突的元素存入到该单元的一种方法。在开放定址法中解决冲突的方法有:线行探查法、平方探查法、双散列函数探查法等。原创 2024-03-12 14:51:43 · 359 阅读 · 0 评论 -
Android中ANR机制
ANR时对用户可感知,比如拥有当前前台可见的activity的进程,或者拥有前台通知的fg-service的进程,这些是用户可感知的场景。input是在每次收到新的input事件时开始检测,并在开始事件派发时设置埋雷时间点,同时检查队列中所有待处理的事件是否有正在处理并且超时的,有则ANR, 没有则重置所有事件ANR超时时间。引爆炸弹:中控系统立即封装现场,抓取快照,搜集目标执行慢的罪证(traces),便于后续的案件侦破(调试分析),最后是炸毁目标。input则采用的就是这种机制。原创 2024-03-12 11:47:13 · 469 阅读 · 0 评论 -
RecyclerView三种局部刷新实现
在Adapter中获取数据不直接从model中获取,而改为从AsyncListDiffer中获取。实质仍然是对DiffUtil的包装。2. 使用DiffUtil, 只更新数据有变化的item, 25.1.0版本开始支持。3. AsyncListDiffer,数据比较在子线程,27.1.0版本开始支持。1. RecyclerView自带的局部刷新。缺点:数据比较在主线程,可能ANR。缺点:要知道数据变化index。原创 2024-03-12 11:37:09 · 1020 阅读 · 0 评论 -
Handler实现原理
Handler是Android中提供的一种异步回调机制,也可以理解为线程间的消息机制。为了避免ANR,我们通常会把一些耗时操作(比如:网络请求、I/O操作、复杂计算等)放到子线程中去执行,而当子线程需要修改UI时则子线程需要通知主线程去完成修改UI的操作,则此时就需要我们使用Handler机制来完成子线程与主线程之间的通信。这种实现方式的好处是,无需在Handler的创建位置重写handleMessage方法,直接在发送Runnable时在Runnable的run方法中实现消息的处理逻辑即可。原创 2024-03-12 09:57:48 · 470 阅读 · 0 评论 -
Android自定义binder实现进程间通信
服务中创建一个binder实例, 在接收到客户端的连接时,向请求方返回回binder的引用。用即可调用其binder.transact方法与远端进行通信。transact有三个个关键参数,分别是消息的命令码、入参及返回值的引用。定义一个binder的服务(在androidManifest.xml中声明)接受远端请求。调用bindService方法,根据Binder服务名称建立与服务的连接。连接成功后, 可以获得远程服务中binder的引用。原创 2024-03-12 09:21:10 · 485 阅读 · 0 评论 -
Android中多线程实现
我们使用Thread类时,可以创建Thread的子类并重写其run方法, 或者自定义一个实现Runable协议的类,然后将其与Thread进行绑定。AsyncTask只能在UI线程调用,一般作为Activity的子类, 以便在重写的方法中访问 Activity中的属性和数据。Android中多线程主要有三种实现方式:通过Thread类、AsyncTask或者RxJava。使用RxJava的好处是,通过采用这种封装好的异步调度框架,可以大大简化线程间切换的过程。2. 通过AsyncTask。原创 2024-03-11 17:43:58 · 596 阅读 · 0 评论 -
Android App冷启动耗时优化
Android应用启动过程,主要包含app::onCreate及执行前的Application阶段及Activity::onCreate执行之后的Activity阶段,以及两个阶段之间的间隙handleMessage阶段和最终页面渲染上屏完成前数据加载阶段四个区间组成。在app:onCreate执行完成后,主线程会收到大量来自子线程的消息,当主线程执行完这些任务后,才会开始调用Activity的onCreate方法,开启应用首屏页面的解析、布局、绘制过程。这一阶段是我们最早的执行预加载的时机。原创 2024-03-11 12:45:19 · 512 阅读 · 0 评论 -
Android中单例模式正确实现方式
instance为null时加锁,不为null时不加锁,效率有提升,但由于android编译优化,有可能类未完成构造函数的调用, 就已经将instance指向了分配的地址空间,进而根据instance是否为空判断是否加锁不可靠,导致线程不安全。注意, 这里加的是synchronized(Singleton.class)字节码锁, 因为class对象在工程启动后是唯一的。volatile关键字的作用是, 禁止指令重排序,保证多线程时每次访问该变量时, 都从主内存中更新该变量在本线程中的本地副本。原创 2024-03-11 10:38:58 · 569 阅读 · 1 评论 -
volatile能保证线程安全吗
根据java的内存管理模型(JMM),所有的共享变量都存储于主内存(包括实例变量和类变量,不包含临时变量),每一个线程还存在自己的工作内存,线程的工作内存,保留了被线程使用的变量的工作副本。如果多线程调用increase方法,可能两个线程同时获取mCount,执行mCount+1,然后都赋值结果2, 即多线程访问时,可能打印出重复的值。volatile关键字的作用是, 禁止指令重排序,即在多线程访问该变量时, 每次都从主内存中更新该变量在本线程中的本地副本。volatile只能保证这3步不被重排序。原创 2024-03-11 10:21:46 · 615 阅读 · 0 评论 -
Android主界面多Tab实现方式
每个页面都各自继承Framement, 可以方便的在onCreateView实现比较复杂的页面逻辑,并且页面逻辑与主界面逻辑分离。实现方式和(3)是一致,但是使用了TabPageIndicator作为tab的指示器,可以实现更丰富的效果,同时也适用于顶部多Tab场景。支持滑动切换Tab,页面不必是Fragment, 直接使用普通的自定义View即可。优点类似RecyclerView。封装最少, 需要自己通过FragmentManager管理Fragment的显示和隐藏,缺点事。不支持滑动切换Tab。原创 2024-03-11 09:59:50 · 696 阅读 · 0 评论 -
Android中MultiDex优化
启动App的时候,先显示一个简单的Splash闪屏界面,然后启动Worker线程执行MultiDex#install(Context)工作,就可以避免UI线程阻塞。缺陷:需要手动分包, 确保应用正常启动,并且启动MultiDex#install(Context)所需要的类都在主dex里面,而且需要处理好进程同步问题。大致思路是,使用内置的apk更新功能把新版本的apk文件下载下来后,先在Worker线程里做好MultiDex的解压和Optimize工作。(2)异步MultiDex方案。原创 2024-03-11 09:47:18 · 557 阅读 · 0 评论 -
Android中进程保活方式
(3)Jobservice,在系统空闲时间或其它指定条件执行一些任务。获取系统的Jobscheduler,向其发送自定义的任务交由其进行统一调度,系统会在自定义任务指定的时机回调onStartJob方法,在Jobservice中实现该方法即可。这里的任务可以是通过Handler向主线程发送个事件,主线程可以什么都不做,或者只要打印下日志即可。(2)前台服务,主要用于特定的后台继续执行的场景,如音乐。(1)一像素acitivity前台运行方式, 不推荐, 即使系统资源不足,也强制运行,太暴力,不推荐使用。原创 2024-03-11 09:38:49 · 534 阅读 · 0 评论 -
Android中View对象的实例化方式
LayoutInflater的inflate方法,除了需要传入Context和Xml布局中的resId外,还有一个可选参数,用来标识生成的view是否需要挂载到父View上。View.inflate主要用于自定义View场景,该方法的第三个参数为父视图,若该参数为null,或者传入的viewGroup的rootview为null,view.getLayoutParams()无法获取视图的布局参数。不过,这种方式也存在较大限制,要求resId标识的视图必须严格是方法调用对象的子视图。原创 2024-03-11 09:27:58 · 571 阅读 · 0 评论