1.Activity
1.1 Activity的启动流程
先来安利一些知识点:
1.zygote 1、Android是基于Linux系统的,而在Linux中,所有的进程都是由init进程直接或者是间接fork出来的,zygote进程也不例外 2、Android系统开启新进程的方式,是通过fork第一个zygote进程实现的。除了第一个zygote进程,其他应用所在的进程都是zygote的子进程
2.SystemServer SystemServer也是一个进程,而且是由zygote进程fork出来的,fork过程,在zygote开启的时候,会调用ZygoteInit.main()进行初始化 ZygoteInit.java 的路径:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
ZygoteInit的main()方法,我们可以看到:
try{
...
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids,
parsedArgs.mRuntimeFlags,
null,
parsedArgs.mPermittedCapabilities,
parsedArgs.mEffectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
SystemServer.java 的路径:/frameworks/base/services/java/com/android/server/SystemServer.java
我们查看SystemServer的main()方法
new SystemServer().run();
run()方法中,ActivityThread在这里初始化了,同时会启动android多个核心服务
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
final Context systemUiContext = activityThread.getSystemUiContext();
systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
}
private void startBootstrapServices() {
...
//初始化ActivityManagerService
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
//初始化电源管理服务
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
// Now that the power manager has been started, let the activity manager
// initialize power management features.
traceBeginAndSlog("InitPowerManagement");
mActivityManagerService.initPowerManagement();
//初始化应用包管理服务
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();
...
}
ActivityMangerService(属于SystemServer进程) 管理所有activity的生命周期,在Activity生命管理中AMS作为一种服务端对象, ,某个activity需要打开另一个activity,需要把对应activity包名类名通过Binder进行IPC传给ActivityMangerService, AMS控制当前activity 调用onPause()、onStop(),并且通过socket进行IPC来通知Zygote进程fork 出一个新进程(主要是ActivityThread) 供新app运行,每个Activity的启动过程则由其所属的进程具体来完成
ActivityThread 对外与AMS进程通过Binder 进行通信,比如告知AMS需启动另一个程序,接受来自AMS的指令暂停当前activity, 对内(app进程内),初始化了一个Instrumentation来具体控制调用activity 的生命周期方法
我们来看一个ActivityThread 如何与AMS通信,启动另一个activity
从 startActivity()一路进来,我们会跟到Activity类中这样一段代码:
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
...
}
我们进到Instrumentation类中
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
...
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
而ActivityManager.getService() 获得的正是实现了IActivityManager接口(aidl文件)的 ActivityManagerService 的引用
/**
* @hide
*/
@UnsupportedAppUsage
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
@UnsupportedAppUsage
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
这样就自然而然的调用到了AMS 的startActivity()方法,通过aidl完成通信。
android 7.1 及以前版本(API<26) ActivityThread 通过与AMS的远程代理接口ActivityManagerProxy实现与AMS的进行IPC Instrumentation执行完execStartActivity时,是这样调用的
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
...
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
ActivityManagerNative.getDefault返回的是ActivityManagerService的远程接口,即ActivityManagerProxy AMS、ActivityManagerProxy都实现了同一个接口——IActivityManager
public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
//从类声明上,我们可以看到ActivityManagerNative是Binder的一个子类,而且实现了IActivityManager接口
static public IActivityManager getDefault() {
return gDefault.get();
}
//通过单例模式获取一个IActivityManager对象,这个对象通过asInterface(b)获得
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
}
所以对AMS 的访问就变成了对ActivityManagerProxy的访问
继续进行,调用到AMS的startActivity()之后一顿调用,到了
public final int startActivityAsUser(...) {
...
// TODO: Switch to user app stacks here.
return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
...
.setMayWait(userId)
.execute();
mActivityStartController.obtainStarter(),返回一个ActivityStarter,执行execute()的代码是这样的
int execute() {
try {
// TODO(b/64750076): Look into passing request directly to these methods to allow
// for transactional diffs and preprocessing.
if (mRequest.mayWait) {
return startActivityMayWait(mRequest.caller, mRequest.callingUid,
...
} else {
return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
...
}
} finally {
onExecutionComplete();
}
}
继续一顿操作....(API<26)的源码之后是调用到 ActivityStack.startActivityLocked(),之后会调用 ActivityStack.resumeTopActivityInnerLocked() ,之后是 startPausingLocked,最终调用ActivityThread.performPauseActivity()暂停指定Activity
1.2 onConfigurationChanged()
通常activity在AndroidManifest文件中不不进行ConfigChange配置,当屏幕方向发生改变时,Activity会被销毁重建,如果有配置configChange="orientation|screenSize",则Activity不会被销毁重建,而是调用onConfigurationChanged方法
在上面的配置的情况下,如果语言改变了,Acitivyt会销毁重建,且不会调用onConfigurationChanged方法
扩展:
当用户接入一个外设键盘时,默认软键盘会自动隐藏,系统自动使用外设键盘.这个过程Activity的销毁和隐藏执行了两次.
并且onConfigurationChanged()周期不会调用.
其中一次的销毁重建可以肯定是因为外设键盘的插入和拔出.当设置android:configChanges="keyboardHidden|keyboard"之后.就不会销毁重建,而是调用onConfigurationChanged()方法
但是还有一次销毁重建一直存在,因为使用外设键盘,触摸屏不能使用了,除了键盘类型的改变,触摸屏也发生了变化,所以会多调用一次
1.3 onSaveInstanceState()和onRestoreInstanceState()
- 1.如果是用户自动按下返回键,或程序调用finish()退出程序,是不会触发onSaveInstanceState()和onRestoreInstanceState()的.
- 2.每次用户旋转屏幕时,您的Activity将被破坏并重新创建.当屏幕改变方向时,系统会破坏并重新创建前台Activity,因为屏幕配置已更改,
您的Activity可能需要加载替代资源(例如布局).即会执行onSaveInstanceState()和onRestoreInstanceState()的.
也就是说,当系统开始停止您的Activity时,它会调用onSaveInstanceState()(1),以便您可以指定要保存的其他状态数据,
以防Activity必须重新创建实例.如果Activity被破坏并且必须重新创建相同的实例,则系统将(1)中定义的状态数据传递给onCreate()方法(2)和onRestoreInstanceState()方法(3), 在oncreate ()中恢复数据需要判断 // 检查是否正在重新创建一个以前销毁的实例 if (savedInstanceState != null) {} 然后才能在bundle中取数据
1.4 setResult()应该在什么时候调用
方式1.按BACK键从一个Activity退出来的,一按BACK,android就会自动调用Activity的finish()方法,
方法:重写onBackPressed()方法,捕获BACK事件,捕获到之后先setResult(), 然后super.onBackPressed()
方式2:按点击事件中显式的调用finish(),
方法:setResult(RESULT_OK);
finish();
2.Service
1.Service的onCreate,onStartCommand,onDestory等全部生命周期方法都运行在UI线程,ServiceConnection里面的回调方法也是运行在UI线程
2.startService 启动的服务在启动后与activity就没有关联了,不受影响,独立运行
3.bindService启动的服务开启后与activity 有关联,activity退出时,也必须调用unbindService来停止服务
我们注意到activity 实现的ServiceConnection 类中重写的 onServiceConnected方法的第二个参数也是IBinder类型的,不难猜测onBind()方法返回的对象被传递到了这里.也就是说我们可以在onServiceConnected方法里拿到了MyService服务的内部类MyBinder的对象(继承自Binder),通过这个内部类对象,只要强转一下,我们可以调用这个内部类的非私有成员对象和方法,因为内部类持有外部类的引用,我们也可以拿到Service 的属性和方法.4.最后还有一点,同一个服务可以用两种方式一同开启,没有先后顺序的要求,MyService的onCreate只会执行一次.
关闭服务需要stopService和unbindService都被调用,也没有先后顺序的影响
3.ContentProvider
介绍
ContentProvider 是Android中提供的专门用于不同应用进行数据共享的方式,它是一种进程间的通信,底层是用Binder实现的.
ContentProvider是系统为我们封装的,使得我们无须关心底层细节即可轻松实现IPC
1.系统给我们提供了许多ContentProvider,比如通信录,日程表信息等,要跨进程访问这些信息,只需要通过ContentResolver的
query,update,insert和delete方法即可. 使用游标cursor 进行操作时记得及时关闭
2.ContentProvider的生命周期
自定义一个ContentProvider只需继承ContentProvider类并实现六个抽象方法即可:onCreate,query,update,insert,delete和
getType.onCreate代表ContentProvider的创建,一般来说我们需要做一些初始化工作,android ContentProvider
的onCreate早于Application的onCreate而执行.
3.ContentProvider的onCreate和CRUD运行在哪个线程及线程安全问题
根据Binder的工作原理,我们知道这六个方法均运行在ContentProvider的进程中,
除了onCreate由系统回调并运行在主线程中,其他五个方法均由外界回调并运行在Binder线程池中
不是线程安全的,而如果在同一个进程访问ContentProvider,根据Binder的原理,同进程的Binder调用就是直接的对象调用,
这个时候CRUD运行在调用者的线程中.另外,ContentProvider的内部存储不一定是sqlite,它可以是任意数据.比如使用普通文件
自定义contentProvider:
<provider
android:name=".xxx.xxxProvider"
android:authorities="com.cwx.test.xxxProvider"
android:permission="com.cwx.provider" //申明外界访问需要的权限
android:process=":provider" //表面运行在独立进程
>
</provider>
外界访问方式:
Uri uri = Uri.parse("content://com.cwx.test.xxxProvider");
getContentResolver().query(uri,null,null,null,null);
注意点
1.当通过增删改方法导致ContentProvider数据发生变化时需要通过ContentResolver的notifyChange方法来通知外界数据发生改变.
2.可以调用ContentResolver的registerContentObserver方法来注册观察者,通过unregisterContentObserver方法来反注册观察者.
3.query,update,insert,delete存在多线程并发访问,需要做好线程同步.
4.BoradCastReciver 广播
应用场景:
1.同一app内部的同一组件内的消息通信(单个或多个线程之间);
2.同一app内部的不同组件之间的消息通信(单个进程);
3.同一app具有多个进程的不同组件之间的消息通信;
4.不同app之间的组件之间消息通信;
5.Android系统在特定情况下与App之间的消息通信.
注意:
1.在Android 8.0的平台上,应用不能对大部分的广播进行静态注册,也就是说,不能在AndroidManifest文件对有些广播进
行静态注册,这里必须强调是有些广播还是能够注册的.比如,接收Android 开机的广播通过静态注册还是能够正常接收的