ActivityTaskView
新版使用方法
Github地址:https://github.com/rome753/ActivityTaskView
-
安装ActivityTaskView release app,启动并给予悬浮窗权限
https://github.com/rome753/ActivityTaskView/releases
或者从 Google Play下载安装。 -
在你开发的App中加入如下类https://github.com/rome753/ActivityTaskView/blob/master/app/src/main/java/cc/rome753/demo/ActivityTaskHelper.java
-
在你开发的App的Application的onCreate()中加入代码
@Override
public void onCreate() {
super.onCreate();
if(BuildConfig.DEBUG) {
ActivityTaskHelper.init(this);
}
}
- 启动你的App,在ActivityTaskView的悬浮窗中能看到App中所有Activity和Fragment的生命周期。
LaunchMode分析
有了这个工具,分析Activity的LaunchMode就很直观了,一图胜千言。
standard mode
标准模式,启动直接加到栈顶,销毁后移除。
singletop mode
栈顶唯一,如果栈顶存在就不会重复启动,保证栈顶不会有两个相同的Activtiy
singletask mode
栈内唯一,如果栈内存在,再次启动时会自动把它上面的其他Activity全部清除(调用onDestroy)
singleinstance mode
独占一栈,启动时会建立新栈切换过去,如果启动了普通Activity又会切换回原来的共享栈(新栈仍然存在,会在栈内唯一的Activity结束时关闭)
技术实现
Activity是安卓开发中最重要的元素,因为APP绝大部分使用都是操作它。某个应用的Activity都是放在一个或多个任务栈中,有两种方法可以查看任务栈和栈中的活动。
- ADB命令
adb shell dumpsys activity activities
该方法可以获得手机中所有活动的详细数据,然而要从中找到你想分析的活动有点麻烦,而且必须连着电脑。
- 使用ActivityManager
ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> runningTaskInfoList = am.getRunningTasks(10);
for (RunningTaskInfo runningTaskInfo : runningTaskInfoList) {
log("id: " + runningTaskInfo.id);
log("description: " + runningTaskInfo.description);
log("number of activities: " + runningTaskInfo.numActivities);
log("topActivity: " + runningTaskInfo.topActivity);
log("baseActivity: " + runningTaskInfo.baseActivity.toString());
}
该方法只能获取到任务栈的栈顶和栈底的活动,操作起来也麻烦。
总之,目前还没有一种方法能直观地观察Activity任务栈和Activity中的Fragment,像下图这样:
原理
Android4.0以后Application支持ActivityLifecycleCallbacks
和FragmentLifecycleCallbacks
的生命周期回调。
ActivityLifecycleCallbacks
application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
});
在Application中注册这个回调,就能监听到所有Activity的生命周期了,再也不用往一个个Activity的生命周期方法里面加log了,在这个回调里统一搞定。
有了回调监听,就可以从APP启动开始,管理建立的每一个Activity,而Activity的getTaskId()方法可以获取到这个Activity属于哪个任务栈。
Activity和任务栈都有了,后面只是想个方法展示的问题。
FragmentLifecycleCallbacks
private class FragmentLifecycleImpl extends FragmentManager.FragmentLifecycleCallbacks{
@Override
public void onFragmentPreAttached(FragmentManager fm, Fragment f, Context context) {
}
@Override
public void onFragmentAttached(FragmentManager fm, Fragment f, Context context) {
}
@Override
public void onFragmentCreated(FragmentManager fm, Fragment f, Bundle savedInstanceState) {
}
@Override
public void onFragmentActivityCreated(FragmentManager fm, Fragment f, Bundle savedInstanceState) {
}
@Override
public void onFragmentViewCreated(FragmentManager fm, Fragment f, View v, Bundle savedInstanceState) {
}
@Override
public void onFragmentStarted(FragmentManager fm, Fragment f) {
handleFragment(f);
}
@Override
public void onFragmentResumed(FragmentManager fm, Fragment f) {
}
@Override
public void onFragmentPaused(FragmentManager fm, Fragment f) {
}
@Override
public void onFragmentStopped(FragmentManager fm, Fragment f) {
}
@Override
public void onFragmentSaveInstanceState(FragmentManager fm, Fragment f, Bundle outState) {
}
@Override
public void onFragmentViewDestroyed(FragmentManager fm, Fragment f) {
}
@Override
public void onFragmentDestroyed(FragmentManager fm, Fragment f) {
}
@Override
public void onFragmentDetached(FragmentManager fm, Fragment f) {
}
}
同理,在Activity启动时可以给它注册FragmentLifecycleCallbacks来监听Activity中Fragment的变化。不同于Activity在Task中是线性的数据结构,Fragment在Activity中是树状的:一个Activity中可以有多个Fragment,每个Fragment又可以有自己的子Fragment。因此本地需要维护一个树FTree。
FTree.java
public class FTree {
private String tab1 = "" + '\u2502'; // |
private String tab2 = "" + '\u2514' + '\u2500'; // |_
private String tab3 = "" + '\u251c' + '\u2500'; // |-
private Node root;
public FTree() {
root = new Node("");
}
public void add(List<String> list, String lifecycle) {
lifeMap.put(list.get(0), lifecycle);
Node node = root;
while (!list.isEmpty()) {
String s = list.remove(list.size() - 1);
if (!node.children.containsKey(s)) {
Node newNode = new Node(s);
node.children.put(s, newNode);
}
node = node.children.get(s);
}
}
public void remove(List<String> list) {
if (list.isEmpty()) return;
lifeMap.remove(list.get(0));
Node node = root;
while (list.size() > 1) {
String s = list.remove(list.size() - 1);
if (node.children.containsKey(s)) {
node = node.children.get(s);
} else return;
}
String last = list.get(list.size() - 1);
node.children.remove(last);
}
public List<String> convertToList(){
List<String