Android基础组件
Activity
什么是Activity
Activity其实就是一个界面容器。
为什么要用Activity
Activity可以实现前台交互、程序入口,也可以作为布局的容器。
- Activity的基本用法
首先要在AndroidManifest.xml中注册Acitivity,然后要在layout目录下编写对应页面的布局文件,最后要在主视图里面绑定视图。
- Activity的生命周期
我们来看下面这张生命周期的示意图。
那么能看出来,打开页面是onCreate→onStart→onResume这样的顺序;关闭页面是onPause→onStop→onDestory这样的顺序;部分遮挡的时候是Paused的状态,完全遮挡则是Stopped的状态。
另外配置Activity节点的configChange属性,可以控制在修改语言,字体大小,旋转屏幕或者键盘显示隐藏时当前Activity是否要重建,若配置,则会进入onConfigurationChanged这个方法。
- Activity的启动模式
Activity有不同的启动模式,首先是standard默认模式,在这个模式下允许Activity重复出现。
singleTop模式下,系统不允许有连续的重复Activity出现。
而在singleTask模式下,系统不允许同一个栈内有重复的Activity出现。
singleInstance模式下,整个系统中都不允许重复的Activity出现。
Fragment
为什么要用Fragment
为了碎片化动态加载组件的需求,同时加载速度快。
- Fragment的生命周期
我们来看下面的Activity和Fragment之间的生命周期的对比图。
可以看到启动时多出了onCreateView,退出时多出了onPause和onDestroyView。
另外,Fragment生命周期可以通过FragmentTransaction.setMaxLifecycle手动干预。
- Fragment与Activity的交互
Fragment要获取Activity中的组件,可以使用findViewById方法;而Activity要获取Fragment中的组件,可以使用findFragmentById方法。
Service
- Service的基本用法
首先要在AndroidManifest中使用<service.../>标签注册,然后建立相应的Service实现类,最后加载startService()/bindService()。
- Service的生命周期
下图展示了Service的声明周期。
- Service与Activity通信
- 定义Binder子类,并实现getService()方法,返回Service对象
- 实现Service类onBind()方法,返回.上述Binder对象
- 实例化ServiceConnection对象,实现onServiceConnected(方法, 从中获取到Service实例
- Activity中调用bindService()方法,并传递上一步的ServiceConnection对象, 将流程跑起来
- 即Activity可以通过调用Service实例中的方法进行直接通信
Broadcast
Broadcast的基本用法
可以进行静态广播,需要先在AndroidManifest中使用<receiver.../><intent-filter.../>;然后建立相应的实现类,并在该实现类的onReceive()中接收广播,最后通过Context.sendBroadcast()方法发送。
也可以进行动态广播,需要注册Context.registerReceiver()方法。
ContentProvider
ContentProvider的基本用法
生产者要先在AndroidManifest中使用<provider.../>,然后建立i相应的ContentProvider实现类。
消费者要在AndroidManifest中声明权限,然后使用Context.getContentResolver方法来使用。
Intent
控件要启动,就需要用到Intent对象,用来表达一个意图。
1.Intent的基本用法
如果是显式Intent,就需要用setConmponent/setClass来指定具体类,而隐式Intent,就需要指定动作、数据、类别、数据类型、组件、扩展信息或者标志位等信息。
2.Intent的系统能力
Intent也可以实现一些系统能力,例如拨打特定电话、发送短信、打开网页、发送邮件、打开地图并载入定位、拍照、进入特定设置页或者打开应用市场进行特定的搜索。
Android通信组件
Handler
- Handler的基本用法
首先先新建一个Handler,实现handleMessage(Message),然后构造Message:What/setData(),然后在子线程里面发送Message,最后在Handler的handleMessage(Message msg)的主线程更新UI。
- Handler的核心原理
Handler的核心原理如下图所示。Handler先把消息发送到Looper的消息队列里面,在消息队列便可以在子线程进行消息的处理。
Binder
进程间通信有三种方式,共享内存、Binder以及Socket/管道/消息队列。其中Binder的效率比Socket更高,而Linux系统下进程内存是独立的,因此Android也不能实现共享内存的方案。
- Binder的基本用法
在服务端定义一个AIDL文件,实现描述的接口,编写service,如果有实体类的话也要提供jar包。而在客户端就需要拿到AIDL文件,绑定服务来获得接口持有对象。
- Binder的核心原理
Binder的核心原理如下图所示。
而在两个进程直接的信息通信是这样的形式,可以看到是通过内核空间来实现的,这里使用了一个叫做命名共享内存的概念来实现共享。
- 以APP启动为例来看Binder的流程
APP启动的时候Binder流程如下图所示,可以看到要启动APP的时候,先是AMS通过Socket将Zygote唤醒,然后再经过一些初始化来达到APP所在进程。
启动之后再通过Binder通信告诉AMS自己已经启动,然后AMS在使用Binder来启动根Activity。
这里有一个问题,为什么AMS和Zygote的通信是通过Socket而不是Binder呢?
首先,先看下安卓系统启动顺序:
从图中可以知道,binder驱动是早于init进程加载的。而init进程是安卓系统启动的第一个进程。
安卓中一般使用的binder引用,都是保存在ServiceManager进程中的,而如果想从ServiceManager中获取到对应的binder引用,前提是需要注册,而注册的行为是在对应的逻辑代码执行时才会去注册的。
实际上,虽然Init进程是先创建ServiceManager,后创建Zygote进程的。虽然Zygote更晚创建,但是也不能保证Zygote进程去注册binder的时候,ServiceManager已经初始化好了。
所以,AMS无法获取到Zygote的binder引用,这才使用LocalSocket来代替binder通信。