不知道大家在开发的时候,会不会经常碰到这样的情况,当你接手一个新项目的时候,如果某个页面出现bug,或是需要知道当前页面的类名,有时候不知道怎么下手,可能会先看代码,找到主Activity,再一步一步的定位到当前页面的类名,但是这样子效率太低。又或者通过在cmd中执行下面的命令来获取当前页面所属的Activity:
adb shell dumpsys activity|findstr ResumedActivity
这样子确实直观了不少,但是我们知道有的Activity里面会有很多Fragment,那又怎么知道是哪个Fragment呢?
于是我就萌生了一个想法,是不是可以通过点击页面的某个地方,像标题栏,就能一下子把当前页面的结构,是哪个Activity,这个Activity里面有多少个Fragment,各自叫什么名称等这些信息一次性打印出来。有了这个想法之后,其实实现思路也是可以摸索到的。
首先通过ActivityManager.getRunningTasks(1).get(0)获取当前页面的Activity类名:
ActivityManager manager = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager.RunningTaskInfo info = manager.getRunningTasks(1).get(0);
String packageName = info.topActivity.getPackageName();
String className = info.topActivity.getClassName();
然后通过FragmentManager().getFragments()获取activity包含的所有Fragment:
for (Fragment fragment : activity.getSupportFragmentManager().getFragments()) {
//解析数据
}
通过这两个方法就可以知道当前前台Activity是哪一个以及该Activity包含了多少个Fragment,各自叫什么。
但是怎么知道当前前台Fragment,也就是正与用户交互的Fragment,这里说一下在使用ViewPager切换Fragment时,对于FragmentPagerAdapter或FragmentStatePagerAdapter建议指定BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT标识:
view_pager.adapter = object : FragmentPagerAdapter(supportFragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
override fun getItem(position: Int) = fragmentList[position]
override fun getCount() = fragmentList.size
}
之后Fragment在可见时都会调用onResume()方法,此时Fragment的isResume()为true,不可见时会调用onPause()方法,利用这个性质就可以判断前台Fragment了,利用这个特定还可以实现Fragment的懒加载,具体实现可以参考我的另一篇博客,ViewPager+Fragment实现懒加载
通过这些方法,就可以解析当前页面结构了,所有的方法我已经封装在一个仓库中:
GitHub - xuzhb24/UIParse: 页面解析工具
具体使用方式:
可以在build.gradle导入依赖:
implementation 'com.github.xuzhb24:uiparse:1.0.3'
同时需要在Project的build.gradle的repositories下加入jitpack:
maven { url "https://jitpack.io" }
之后在根Activity或具体Activity中重写dispatchTouchEvent,加入ParseUtil.showTopActivityInfo(this, ev)这一行代码即可:
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
//屏幕顶部中间区域双击获取当前Activity类名
if (BuildConfig.DEBUG) { //只在debug环境有效
ParseUtil.showTopActivityInfo(this, ev)
}
return super.dispatchTouchEvent(ev)
}
Activity需继承AppCompatActivity,之后双击屏幕顶部中间部分就可以得到当前页面结构信息了。
最后写了个Demo看一下效果,这个Demo中MainActivity由三个Fragment组成,从左往右依次是HomeFragment(首页)、VideoFragment(视频)、MineFragment(我的),其中HomeFragment里面又包括了3个Fragment,从左到右依次为FirstFragment(第一页),SecondFragment(第二页),ThirdFragment(第三页),页面如下:
双击屏幕顶部中间部分,会弹出一个对话框:
前台Activity是MainActivity,前台Fragment是HomeFragment里面的FirstFragment,再来验证一下,切换到视频页,双击屏幕顶部中间区域,
此时前台Fragment变成了VideoFragment,点击VideoActivity按钮跳转进VideoActivity,再双击屏幕顶部中间部分,可以看到VideoActivity的页面构造:
此时前台Activity是VideoActivity,前台Fragment是VideoFirstFragment。
回到首页,会看到有几个SupportRequestManagerFragment,这个并不是我添加的,其实这个是因为我在项目中使用了Glide,Glide感知生命周期的原理是往当前的页面添加一个隐藏的Fragment,因为Fragment的生命周期和Activity是同步的,通过这个Fragment对生命周期进行处理,而这个Fragment就是SupportRequestManagerFragment。