本文已参与「新人创作礼」活动,一起开启掘金创作之路。
ProcessPhoenix是大神jakewharton开源的一款Android平台开源库, 主要用于优化Android应用的进程重启. 该库只应该用于在测试构建阶段时基础状态的改变, 比如从staging阶段向生产阶段的转变.
ProcessPhoenix本意凤凰进程, 所谓涅槃重生, 即指重启进程.
Usage
启动应用内默认的Launcher Activity:
ProcessPhoenix.triggerRebirth(context);
或是不想重启应用, 只想重启特定的组件, 相关API为:
Intent nextIntent = //...
ProcessPhoenix.triggerRebirth(context, nextIntent);
因为Phoenix处于单独的进程, 若App启动时处于Phoenix进程, App的相关初始化操作应该在Application#onCreate中跳过该进程.
if (ProcessPhoenix.isPhoenixProcess(this)) {
return;
}
Under the hood
ProcessPhoenix作为一个Activity, 运行于单独的进程. 它的核心作用是在ProcessPhoenix#onCreate中启动别的应用的默认Launcher或者其它基础组件, 之后再杀死自身进程.
这部分信息从ProcessPhoenix源码可知:
/**
* Process Phoenix facilitates restarting your application process. This should only be used for
* things like fundamental state changes in your debug builds (e.g., changing from staging to
* production).
* <p>
* Trigger process recreation by calling {@link #triggerRebirth} with a {@link Context} instance.
*/
public final class ProcessPhoenix extends Activity {
...
//利用Activity#startActivities(Intent[] intents)启动多个组件.
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ArrayList<Intent> intents = getIntent().getParcelableArrayListExtra(KEY_RESTART_INTENTS);
startActivities(intents.toArray(new Intent[intents.size()]));
finish();
Runtime.getRuntime().exit(0); // Kill ProcessPhoenix process.
}
}
在ProcessPhoenix#AndroidManifest.xml, ProcessPhoenix声明为:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jakewharton.processphoenix" >
<uses-sdk android:minSdkVersion="11" />
<application>
<activity
android:name="com.jakewharton.processphoenix.ProcessPhoenix"
android:process=":phoenix"
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
</application>
</manifest>
由此可知, ProcessPhoenix是一个背景透明且无UI的Activity, 其所在进程名称为: com.jakewharton.processphoenix:phoenix
此外, ProcessPhoenix剩余源码为:
public final class ProcessPhoenix extends Activity {
private static final String KEY_RESTART_INTENTS = "phoenix_restart_intents";
/**
* 启动App的默认Launcher Activity
*/
public static void triggerRebirth(Context context) {
triggerRebirth(context, getRestartIntent(context));
}
/**
* 启动Context所在进程的一个或多个特定组件
*/
public static void triggerRebirth(Context context, Intent... nextIntents) {
Intent intent = new Intent(context, ProcessPhoenix.class);
intent.addFlags(FLAG_ACTIVITY_NEW_TASK); // In case we are called with non-Activity context.
intent.putParcelableArrayListExtra(KEY_RESTART_INTENTS, new ArrayList<>(Arrays.asList(nextIntents)));
context.startActivity(intent);
if (context instanceof Activity) {
((Activity) context).finish();
}
Runtime.getRuntime().exit(0); // Kill kill kill!
}
//获取Context所在App的默认Launcher
private static Intent getRestartIntent(Context context) {
Intent defaultIntent = new Intent(ACTION_MAIN, null);
defaultIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
defaultIntent.addCategory(CATEGORY_DEFAULT);
String packageName = context.getPackageName();
PackageManager packageManager = context.getPackageManager();
for (ResolveInfo resolveInfo : packageManager.queryIntentActivities(defaultIntent, 0)) {
ActivityInfo activityInfo = resolveInfo.activityInfo;
if (activityInfo.packageName.equals(packageName)) {
defaultIntent.setComponent(new ComponentName(packageName, activityInfo.name));
return defaultIntent;
}
}
throw new IllegalStateException("Unable to determine default activity for "
+ packageName
+ ". Does an activity specify the DEFAULT category in its intent filter?");
}
...
/**
* 判断当前进程是否是ProcessPhoenix临时进程.
* 因此需要在自己应用中Application#onCreate时, 判断当前进程为ProcessPhoenix临时进程时, 主动跳过原本属于应用自身初始化相关资源的过程.
*/
public static boolean isPhoenixProcess(Context context) {
int currentPid = Process.myPid();
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> runningProcesses = manager.getRunningAppProcesses();
if (runningProcesses != null) {
for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) {
if (processInfo.pid == currentPid && processInfo.processName.endsWith(":phoenix")) {
return true;
}
}
}
return false;
}
}
Yeah, jakewharton is absolutely a m...ker! //这绝对是一句赞扬的话