Java动态代理
JDK动态代理
通过java.lang.reflect.Proxy可以实现动态代理,但是这种方式只能作用于接口,如果一个类没有接口则无法实现动态代理。
1 | //Interface是一个接口,InterfaceImpl是接口的实现类 |
CGLIB实现动态代理
CGLIB通过动态生成一个代理类的子类来提供代理。但是对于final方法,是无法实现代理的。
通过java.lang.reflect.Proxy可以实现动态代理,但是这种方式只能作用于接口,如果一个类没有接口则无法实现动态代理。
1 | //Interface是一个接口,InterfaceImpl是接口的实现类 |
CGLIB通过动态生成一个代理类的子类来提供代理。但是对于final方法,是无法实现代理的。
本文创建了一个独立进程的service,通过bind方式来绑定服务,并通过binder与service进行交互。基于此来分析binder交互机制。
定义aidl接口:
1 | //IRemote.aidl |
IRemote是service的对外接口,TalkCallback则用于从service回调client端,加入TalkCallback是为了更好的理解service和client相互调用的流程。
定义完aidl后,编译一遍项目,这样就可以生成对应的java类,对应的java类在app/build/generated/aidl_source_output_dir目录下。
定义Service:
1 | public class RemoveService extends Service { |
因为我们要定义一个独立进程的service,所以在AndroidManifest.xml要声明android:process属性,如下:
1 | <service |
这样一个独立进程的service就定义完成了,然后就可以使用了。
先看下app端的类图结构:
IWindowManager在IWindowManager.aidl文件中定义,是WindowManagerService的对外接口。
每个app都会有一个Window Session用于与window manager进行交互。IWindowSession是通过aidl定义的binder接口,app通过IWindowSession与WMS进行交互。
zenuml
new ViewRootImpl() {
WindowManagerGlobal.getWindowSession {
//sWindowSession是WindowManagerGlobal的静态类变量
//如果sWindowSession为空就通过WMS.openSession来打开一个
if (sWindowSession == null) {
WindowManagerService.openSession {
new Session()
}
}
return sWindowSession
}
}
IWindow加入到WMSIWindow是一个binder接口,这个binder的service端是app,实现类是ViewRootImpl.W,client端是WMS。WMS会通过IWindow这个binder接口来通知app window相关的事件。先看下addWindow的调用时序:
如果现有项目还不支持C/C++,则可以通过如下步骤来加入C/C++

然后按照步骤操作即可。添加完成后打开app\src\main\cpp\CMakeLists.txt文件,修改项目名称
我们在me.rjy.android.demo.MainActivity中定义一个native函数,并加载native库。
Java代码:
1 | public class MainActivity extends AppCompatActivity { |
Kotlin代码:
1 | class MainActivity : ComponentActivity() { |
本文以时序图的形式来展示activity的启动过程,相比于贴源码会更加直观。本文的讲解的流程是基于MainActivity使用standard模式启动SecondActivity,且两个Activity都在同一个应用中,最后的部分也会讲解一下进程的启动。
zenuml
group App {
<<App>> act as Activity
<<App>> ins as Instrumentation
}
group AMS {
<<AMS>> atms as ActivityTaskManagerService #F0F8FF
ActivityStarter #F0F8FF
}
act.startActivity {
act.startActivityForResult {
ins.execStartActivity {
atms.startActivity {
atms.startActivityAsUser {
//没有缓存则创建
new ActivityStarter()
ActivityStarter."① execute"
}
}
}
}
}
zenuml
<<AMS>> ActivityStarter #F0F8FF
ActivityStarter."① execute" {
executeRequest {
new ActivityRecord()
startActivityUnchecked {
startActivityInner {
Task.addChild
Task.startActivityLocked
RootWindowContainer.resumeFocusedTasksTopActivities {
Task.resumeTopActivityUncheckedLocked {
resumeTopActivityInnerLocked {
TaskFragment.resumeTopActivity {
//pause当前activity
"② startPausing()"
if (! isProcessRunning) {
ActivityTaskManagerService.startProcessAsync
}
}
}
}
}
}
handleStartResult
postStartActivityProcessing
}
}
}
启动SecondActivity之前会先执行MainActivity的pause操作:
在Android 9之前的版本,ActivityThread中通过LAUNCH_ACTIVITY消息来启动activity,源码如下:
1 | //android\app\ActivityThread.java |
但从Andorid 9开始,ActivityThread去掉了LAUNCH_ACTIVITY PAUSE_ACTIVITY RESUME_ACTIVITY等消息,而是改成了EXECUTE_TRANSACTION,通过ClientTransaction这套机制来执行activity生命周期流程,相关源码如下:
Android View的整个绘制流程包含了3个阶段,分别是measure、layout、draw。measure用于计算View的宽高,结果放在mMeasuredWidth和mMeasuredHeight中;layout的作用是计算view及其子view的位置;draw的作用就是将View真正的绘制到显示屏上。
当activity首次启动,或者更新View(如TextView重新设置text)时,都会走到ViewRootImpl.scheduleTraversals来触发View的渲染流程。
zenuml
ViewRootImpl.scheduleTraversals {
"主线程消息循环插入同步屏障"
Choreographer."postCallback:mTraversalRunnable" {
scheduleFrameLocked {
scheduleVsyncLocked {
FrameDisplayEventReceiver.scheduleVsync()
}
}
}
}
FrameDisplayEventReceiver.onVsync {
Looper."发布一个同步消息"
}
Looper.run {
Choreographer.doFrame {
"doCallbacks(Choreographer.CALLBACK_INPUT, ...)"
"doCallbacks(Choreographer.CALLBACK_ANIMATION,...)"
"doCallbacks(Choreographer.CALLBACK_INSETS_ANIMATION,...)"
"doCallbacks(Choreographer.CALLBACK_TRAVERSAL,...)" {
ViewRootImpl."mTraversalBarrier.run" {
ViewRootImpl.doTraversal {
"删除同步屏障"
performTraversals
}
}
}
"doCallbacks(Choreographer.CALLBACK_COMMIT,...)"
}
}
zenuml
ViewRootImpl.performTraversals {
measureHierarchy {
performMeasure {
DecorView.measure
}
}
relayoutWindow {
IWindowSession.relayout
updateBlastSurfaceIfNeeded {
new BLASTBufferQueue
blastSurface = BLASTBufferQueue.createSurface
"mSurface.transferFrom(blastSurface)"
}
ThreadedRenderer.setSurfaceControl
ThreadedRenderer.setBlastBufferQueue
}
ThreadedRenderer.initialize {
"HardwareRenderer.setSurface"
}
ThreadedRenderer.allocateBuffers
ThreadedRenderer.setup
performMeasure {
DecorView.measure
}
performLayout {
DecorView.layout
}
performDraw {
draw {
ThreadedRenderer.draw
}
}
}
关于relayoutWindow的调用流程可参考Android WindowManager与Window
参考:
在自定义View中一般都会用到onDraw这个函数:
zenuml
ViewRootImpl.draw {
if (isHardwareEnabled()) {
ThreadedRenderer.draw
} else {
drawSoftware
}
}
NativeAllocationRegistry来实现native内存的回收。在android.graphics.BitmapFactory类中有一系列函数可以解码生成Bitmap:
这些方法都会调用到jni层frameworks\base\libs\hwui\jni\BitmapFactory.cpp,最终都会走到doDecode方法:
1 | //frameworks\base\libs\hwui\jni\BitmapFactory.cpp |
1 | bool HeapAllocator::allocPixelRef(SkBitmap* bitmap) { |
注解的使用场景可以分为两种:一)编译期间通过注解解析器处理;2)运行期间反射使用;
RetentionPolicy.SOURCE : 编译期可见,但不会写入到.class文件;RetentionPolicy#CLASS : 会写入到.class文件中,但是会被JVM忽略(这是默认策略);RetentionPolicy#RUNTIME :注解会被写入到.class文件中,并且JVM运行期间也可见,可以通过反射放射获取到;1 | @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER}) |
编译完成后,每个注解都会生成自己的.class文件,看一下MyClass这个注解的.class文件的内容:
1 | $ javap -p -v me/demo/MyClass.class |
从MyClass.class文件第7行代码public interface MyClass extends java.lang.annotation.Annotation可以看出来MyClass实际上是继承自Annotation的接口类。这一点从java.lang.Class#getAnnotation这个方法也可以看出来:
1 | //java/lang/Class.java |
在Android Activity启动流程文章中已经介绍了,在activity的onResume之后,ViewRootImpl#setView(View view, WindowManager.LayoutParams attrs, ...),其中view就是DecorView,ViewRootImpl#setView中就会调用requestLayout,然后调用scheduleTraversals。这是首次调用,后续view的改动都会调用到scheduleTraversals。
1 | //android-12.1.0_r27\frameworks\base\core\java\android\view\ViewRootImpl.java |
在垂直布局的RecyclerView中展示了Item0~Item4这5个TextView,我们现在把Item2删掉。数据更新后,我们调用Adapter#notifyItemRemoved(2)来提交更新。
dispatchLayoutStep1阶段:
dispatchLayoutStep2阶段:
dispatchLayoutStep3阶段: