more
注释之前的内容被视为文章摘要。

前言
对于 Android 开发者来说 Binder 应该不会陌生了,Binder 是 Android 提供的 IPC 通信机制,它是通过内存映射实现的,而这也是 Binder 相对于其他传统进程间通信方式的优点之一,即我们说的 Binder 只需要做“一次拷贝”,而其他传统方式需要“两次拷贝”!
那么,这所谓的“一次拷贝”的实现原理到底是什么?
其实,在 Binder 驱动的源码中有多次 copy_from_user 和 copy_to_user 的调用,根本不止"一次拷贝",但是很多的书籍包括 Android 官方都宣称只有一次拷贝,这是为什么呢?
Android中的消息机制主要指Handler的运行机制。Handler的使用过程很简单,通过它可以轻松地 将一个任务切换到Handler所在的线程中去执行 。Handler在日常开发中的最常用的作用是通过它更新UI。具体来说是这样的:有时候需要在子线程中进行耗时的IO操作,可能是读取文件或者访问网络等,当耗时操作完成以后可能需要在UI上做一些改变,由于Android开发规范的限制,我们并不能在子线程中访问UI控件,否则就会触发程序异常,这个时候通过Handler就可以将更新UI的操作切换到主线程中执行。因此,本质上来说,Handler并不是专门用于更新UI的,它只是常被开发者用来更新UI。
ThreadLocal是通过线程隔离的方式防止任务在共享资源上产生冲突, 线程本地存储是一种自动化机制,可以为使用相同变量的每个不同线程都创建不同的存储。 @pdai
带着BAT大厂的面试问题去理解
- 什么是ThreadLocal? 用来解决什么问题的?
- 说说你对ThreadLocal的理解
- ThreadLocal是如何实现线程隔离的?
- 为什么ThreadLocal会造成内存泄露? 如何解决
- 还有哪些使用ThreadLocal的应用场景?
前言
对于ThreadLocal
,大家的第一反应可能是很简单呀,线程的变量副本,每个线程隔离。那这里有几个问题大家可以思考一下:
ThreadLocal
的 key 是弱引用,那么在ThreadLocal.get()
的时候,发生GC之后,key 是否为null?ThreadLocal
中ThreadLocalMap
的数据结构?ThreadLocalMap
的Hash 算法?ThreadLocalMap
中Hash 冲突如何解决?ThreadLocalMap
的扩容机制?ThreadLocalMap
中过期 key 的清理机制?探测式清理和启发式清理流程?ThreadLocalMap.set()
方法实现原理?ThreadLocalMap.get()
方法实现原理?- 项目中
ThreadLocal
使用情况?遇到的坑? - ……
很多(我就直接代表很多人了🐶)做 Android 的同学认识和学习 ThreadLocal 都是通过 Looper 中的 sThreadLocal 这个静态变量开始的,然后就会进入一个误区:sThreadLocal 是 Looper 中的一个静态变量啊,当
Looper#prepare(boolean quitAllowed)
方法调用sThreadLocal.set(new Looper(quitAllowed))
的时候存到 ThreadLocalMap 中的 value (Looper) 的 key 值竟然是 this,也就是 sThreadLocal 这个静态变量?那一个静态变量怎么能作为 key值呢?静态变量在这个进程中可是独一份啊,其他线程的 Looper 再调用 Looper#prepare(boolean quitAllowed) 的时候岂不会把之前的 Looper 给替代了?
本节将介绍 View 的一个核心知识点:事件分发机制
。
事件分发机制不仅仅是核心知识点更是难点,不少初学者甚至中级开发者面对这个问题时都会觉得困惑。另外,View 的另一大难题滑动冲突
,它的解决方法的理论基础就是事件分发机制,因此掌握好 View 的事件分发机制是十分重要的。本节将深入介绍 View 的事件分发机制,在这一篇会对事件分发机制进行概括性地介绍,而在下一篇将结合系统源码去进一步分析事件分发机制。
一、点击事件的传递规则
在介绍点击事件的传递规则之前,首先我们要明白这里要分析的对象就是 MotionEvent
,即点击事件
,关于 MotionEvent 在之前已经进行了介绍。所谓点击事件的事件分发,其实就是对 MotionEvent 事件的分发过程,即当一个 MotionEvent 产生了以后,系统需要把这个事件传递给一个具体的 View,而这个传递的过程就是分发过程。点击事件的分发过程由三个很重要的方法来共同完成:dispatchTouchEvent
、onInterceptTouchEvent
和 onTouchEvent
,下面我们先介绍一下这几个方法。
final 关键字看上去简单,但是真正深入理解的人可以说少之又少,读完本文你就知道我在说什么了。本文将常规的用法简化,提出一些用法和深入的思考。@pdai
带着BAT大厂的面试问题去理解final
提示
请带着这些问题继续后文,会很大程度上帮助你更好的理解final。@pdai
- 所有的final修饰的字段都是编译期常量吗?
- 如何理解private所修饰的方法是隐式的final?
- 说说final类型的类如何拓展? 比如String是final类型,我们想写个MyString复用所有String中方法,同时增加一个新的toMyString()的方法,应该如何做?
- final方法可以被重载吗? 可以
- 父类的final方法能不能够被子类重写? 不可以
- 说说final域重排序规则?
- 说说final的原理?
- 使用 final 的限制条件和局限性?
- 看本文最后的一个思考题
前言
单例模式在Java开发中是非常经典和实用的一种设计模式,在JDK的内部包的好多api都采用了单例模式,如我们熟悉的Runtime类.
单例模式总的来说有两种创建方式,一种是延迟加载的模式,一种是非延迟加载的模式,今天我们来学习一下基于双检锁延迟加载的单例模式。
什么是单例模式
顾名思义,单例模式指的是在整个程序运行期间,我们只能初始化某个类一次,然后一直使用这个实例,尤其是在多线程的环境下,也要保证如此。
基于双检锁的单例模式
在介绍基于双检锁的单例模式下,我们先思考下如何在使用延迟加载的情况下实现一个单例模式,可能有一些比较年轻的小伙伴,不假思索的就写下了下面的一段代码: