Activity
Activity是Android 四大组合之一,在应用中表现为用户界面,显示各种UI元素。
Activity生命周期:onCreate, onStart, onResume, onPause, onStop, onDestroy, onRestart.
Activity视图层级图
从图中可以看出,Acitvity下有个PhoneWindow,这个PhoneWindow是Window实现类,下面包含了一个DecorView,实际上这个才是顶级视图。
Activity 启动模式 standard, singleTop, singleTask, singleInstance
//配置方式
<activity ndroid:launchMode="standard" >
standard-默认模式
每次启动一个Activity都会重写创建一个新的实例,不管这个实例存不存在,这种模式下,谁启动了该模式的Activity,该Activity就属于启动它的Activity的任务栈中。
singleTop-栈顶复用模式
这个模式下,如果新的activity已经位于栈顶,那么这个Activity不会被重写创建,同时它的onNewIntent方法会被调用,需要注意的是这个Activity它的onCreate(),onStart()方法不会被调用,因为它并没有发生改变。
singleTop模式分3种情况
当前栈中已有该Activity的实例并且该实例位于栈顶时,不会新建实例,而是复用栈顶的实例,并且会将Intent对象传入,回调onNewIntent方法.当前栈中已有该Activity的实例但是该实例不在栈顶时,其行为和standard启动模式一样,依然会创建一个新的实例
singleTask-栈内复用模式
如果栈中存在这个Activity的实例就会复用这个Activity,不管它是否位于栈顶,复用时,会将它上面的Activity全部出栈,并且会回调该实例的onNewIntent方法。其实这个过程还存在一个任务栈的匹配,因为这个模式启动时,会在自己需要的任务栈中寻找实例,这个任务栈就是通过taskAffinity属性指定。如果这个任务栈不存在,则会创建这个任务栈。
Service总结
Service 的生命周期相对与Activity 比较简单,只有3个分别为:onCreate、onStartCommand各onDestory。
- 在项目的任何位置调用了Context的startService() 函数,相应的服务就会开启。
首次创建时会调用onCreate方法,然后会回调onStartCommand()函数。 - 服务开启后一直保持运行,直到调用stopService()或stopSelf(),服务会停止。
- 每调用一次startService(),onStartCommand(),就会运行一次,但实际上服务只会创建一个实例。
- service 是运行在UI 线程中,不要直接做耗时操作,否则是新那些子线程。
IntentService 总结
IntentService 是 Android 提供直接运行在子线程的Service.这个只会只会执行一次,执行完后会自动高stopSelf自我销毁。它是Service 的子类。重写onHandleIntent()该方法是在子线程中运行
Android 中的消息机制 总结
先看一张图
image.png
先理解Handler, Looper, MessageQueue, Message 之间的关系,Handler都会关联一MessageQueue,而MessageQueue被封闭在Looper中,而Looper又会关联一个线程,最终就等于每个消息队列都会关联一个线程。
Handler 是一个消息处理器,把Message发送到MessageQueue中,然后在通过对应的线程Looper把消息取出进行处理.也就是说Handler在什么线程处理消息,取决于它对应的Looper所在的线程。
消息是怎样被处理的?答案是通过Looper.loop(),该方法就是一个死循环,然后通过消息队列逐步取出消息,然后调用dispatchMessage(msg);(target 是Handler类型)
image.png在子线程中创建Handler为什么会异常?这是因为该线程中的Looper还没有创建,因为sThreadLocal.get()返回 为NUll,Handler就是与MessageQueue建立联系,如果没有MessageQueue Handler没有存在的意义。
解决方法如下:
//1为当前线程创建Looper,关绑定在ThreadLocal中。
Looper.prepare();
Handler handler =new Handler();
//2启动消息的循环
Looper.loop();
RxJava
1. 定义
RxJava
是一个 基于事件流、实现异步操作的库
2. 作用
实现异步操作
类似于 Android
中的 AsyncTask
、Handler
作用
3. 特点
- 逻辑简洁
- 实现优雅
- 使用简单
更重要的是,随着程序逻辑的复杂性提高,它依然能够保持简洁 & 优雅
4. 实现步骤
- 创建事件 Observable.create
- 创建观察者 Observer
- 订阅observable.subsribe
Retrofit
Retrofit, 其实是对okhttp一个封闭,它本身不做网络请求,只是生成请求的对象。
-
retrofit 扩展
OkHttpClient:Retrofit使用OkHttpClient来实现网络请求,这个OkHttpClient虽然不能替换成其他网络执行框架,比如Volley,但是对他进行扩展,最简单的就是使用它的Interceptor拦截器。 -
addConverterFactory:对返回数据类型的自动转换。
-
addCallAdapterFactory:对网络工作对象callWorker的自动转换。把Retrofit中执行的网络请求的Call对象,转换为接口定义的Call对象。
Retrofit实现原理-函数解析、网络请求、数据转换
image根据接口定义解析函数,得到函数的具体定义,生成对应的ServiceMethod。然后根据这个ServiceMethod,实现一个OkHttpClient的Call对象,负责在Retrofit底层实现网络访问。其中在网络访问返回网络数据,根据ServiceMethod实现数据转换。最后利用适配器,把OkHttpCall对象转换为接口要求的Call网络请求对象
Retrofit 使用流程
- 通过接口来描述请求的行为与请求参数
- 创建Retrofit实例
- 创建一个代理对象
- 接口调用
- 执行与回调
java 动态代理
实现原理
设计动态代理类(DynamicProxy)时,不需要显式实现与目标对象类(RealSubject)相同的接口,而是将这种实现推迟到程序运行时由 JVM来实现
优点
- 只需要1个动态代理类就可以解决创建多个静态代理的问题,避免重复、多余代码
- 更强的灵活性
缺点
- 效率低
相比静态代理中 直接调用目标对象方法,动态代理则需要先通过Java
反射机制 从而 间接调用目标对象方法 - 应用场景局限
使用步骤
- 声明 调用处理器类 (实现InvocationHandler 接口)
- 声明目标对象类的抽象接口
- 声明目标对象类
- 通过动态代理对象,调用目标对象的方法
结论:动态代理增加运行前与运行后的两个切面,一种额外的能力,统一处理需求
Application启动流程
关键类说明
整个启动流程因为会涉及到多次Binder通信,这里先简要说明一下几个类的用途,方便大家理解整个交互流程:
- ActivityManagerService :Android中最核心的服务之一,主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作,它本身也是一个Binder的实现类。
- Instrumentation :它用来监控应用程序和系统的交互。
- ActivityThread :应用的入口类,系统通过调用main函数,开启消息循环队列。ActivityThread所在线程被称为应用的主线程(UI线程)。
- ApplicationThread :ApplicationThread提供Binder通讯接口,AMS则通过代理调用此App进程的本地方法。
- ActivityManagerProxy :AMS服务在当前进程的代理类,负责与AMS通信。
- ApplicationThreadProxy :ApplicationThread在AMS服务中的代理类,负责与ApplicationThread通信。
启动App流程
用户点击Home上的一个App图标, 启动一个应用时:
imageClick事件会调用startActivity(Intent), 会通过Binder IPC机制, 最终调用到ActivityManagerService. 该Service会执行如下操作:
- 第一步通过PackageManager的resolveIntent()收集这个intent对象的指向信息.
- 指向信息被存储在一个intent对象中.
- 下面重要的一步是通过grantUriPermissionLocked()方法来验证用户是否有足够的权限去调用该intent对象指向的Activity.
- 如果有权限, ActivityManagerService会检查并在新的task中启动目标activity.
- 现在, 是时候检查这个进程的ProcessRecord是否存在了.
如果ProcessRecord是null, ActivityManagerService会创建新的进程来实例化目标activity.
创建进程
ActivityManagerService调用startProcessLocked()方法来创建新的进程, 该方法会通过前面讲到的socket通道传递参数给Zygote进程. Zygote孵化自身, 并调用ZygoteInit.main()方法来实例化ActivityThread对象并最终返回新进程的pid.
ActivityThread随后依次调用Looper.prepareLoop()和Looper.loop()来开启消息循环.
流程图如下:
image.png2.2 绑定Application
接下来要做的就是将进程和指定的Application绑定起来. 这个是通过上节的ActivityThread对象中调用bindApplication()方法完成的. 该方法发送一个BIND_APPLICATION的消息到消息队列中, 最终通过handleBindApplication()方法处理该消息. 然后调用makeApplication()方法来加载App的classes到内存中.
流程如下:
image.png2.3 启动Activity
经过前两个步骤之后, 系统已经拥有了该application的进程. 后面的调用顺序就是普通的从一个已经存在的进程中启动一个新进程的activity了.
实际调用方法是realStartActivity(), 它会调用application线程对象中的sheduleLaunchActivity()发送一个LAUNCH_ACTIVITY消息到消息队列中, 通过 handleLaunchActivity()来处理该消息.
假设点击的是一个视频浏览的App, 其流程如下:
image.png
网友评论