android日记(六)
上一篇:android日记(五)
1.怎么将本地项目上传到github
- 本地仓库执行git init
- git add .
- git commit -m "xx"
- github上creat new repository创建新仓库并命名,建好后就有了仓库的地址,复制该地址
- git branch -M master,建立分支
- 执行git remote add origin xxx(远程仓库地址),关联远程仓库
- 执行git push -u origin master ,本地代码推到远程仓库
2.AndroidStudio添加module
- AndroidStudio中File -> new Module -> Phone & Table Module -> Configure Module Name,比如添加了一个名为“othermodule”的module
- 这时project中会出现一个名为othermodule的module,与app主module平级。并且setting.gradle中增加了include 'othermodule'。
include ':othermodule' include ':app'
- 如果编译失败,就需要检查下新加的othermodule的build.gradle,看看当前引入的是plugin是'com.android.application'或者'com.android.library'。
apply plugin: 'com.android.application'
apply plugin: 'com.android.library'
如果是'com.android.application',需要改为'com.android.library'。只有主module才能是'com.android.application',表示该module是可执行工程;而其他module都是'com.android.library',表示库工程。
- 如果还是编译报错,需要再检查othermodule和主module的build.gradle配置是否有冲突,比如applicationId、compileSdkVersion、minSdkVersion、targetSdkVersion、buildToolsVersion等,这些都要保持一致。有些配置,othermodule中没必要再配置,比如applicationId,如果配置了不一样的application就需要删除。
- 各个module的compileSdkVersion、minSdkVersion、targetSdkVersion、buildToolsVersion都要设置且保持一致,这时为了方便管理,将这些版本号定义在project.gradled的project.ext{}中定义全局常量,然后各个module的build.gralde中,使用rootproject来引用这些常量。
- 另外,manifest的配置也可能引起冲突,比如allowBackUp属性,各个module应该配置为一样,要么都为true,要么都为false。同样为了方便日后做统一修改的管理,可以在values/bool.xml中设置boolean值,然后在manifest中的配置bool值从xml中引用。
<?xml version="1.0" encoding="utf-8"?> <resources> <bool name="allow_backup">true</bool> </resources>
这样做的还有个好处就是,对不同系统版本配置不同的bool值,比如v21及以上设置allowBackup=false,而v21以下的设置allowBackup=true。
3.android逆向apk
- 解压apk,有两种方式,一种是把.apk文件重命名为.zip后,解压zip;另一种直接把.apk文件拖入到AndroidStudio。解压出的文件,主要包含AndroidManifest.xml清单、res资源和classes.dex几部分。
- 其中代码都在dex文件中,需要对其反编译后,才能看到源码。使用dex2jar工具,可以将dex文件转为jar包,进入dex2jar路径,执行: d2j-dex2jar X://xxx/xxx/classes.dex,如果执行成功,将得到classes-dex2jar.jar文件。
- 如果上面的命令报错:zsh: command not found: d2j-dex2jar,表示没有执行权限。这时,可以将要进行反编译的apk拖入的dex2jar目录中,在dex2jar路径下,执行,
- chmod u+x d2j_invoke.sh
- chmod u+x d2j-dex2jar.sh
- sh d2j-dex2jar.sh -f -o output_jar.jar activity.apk
这时,在dex2jar目录下,将输入output_jar文件。
- 使用jd-gui工具,可以查看jar包中的源码。打开jd-gui,把jar包拖入到软件中,就可以看到源码了。
4.Android申请悬浮窗权限
- 什么时候需要用到悬浮窗权限,当需要显示window时。
- 在manifest中声明悬浮窗权限
<!-- 悬浮窗 --> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
- 6.0以下声明后就有权限了,6.0以后需要用户授权。
- 与普通权限不同,不能使用requestPermissions()动态申请悬浮窗权限,只能让用户自己去应用设置中开启权限。需要时,可以引导用户去设置页,
/** * 申请悬浮窗 */ @RequiresApi(api = Build.VERSION_CODES.M) private fun requestAlertWindow(requestCode: Int) { val intent = Intent( Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + context!!.packageName) ) startActivityForResult(intent, requestCode)
} - 检查悬浮窗权限是否开启,Setting.canDrawOvelays()的结果,在某些系统版本下并不精确,应该区分不同系统分别来判断。
/**
* 检查悬浮窗权限
*/
@JvmStatic
fun checkFloatPermission(context: Context): Boolean {
return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
try {
var cls = Class.forName("android.content.Context")
val declaredField = cls.getDeclaredField("APP_OPS_SERVICE")
declaredField.isAccessible = true
var obj: Any? = declaredField[cls] as? String ?: return false
val str2 = obj as String
obj =
cls.getMethod("getSystemService", String::class.java).invoke(context, str2)
cls = Class.forName("android.app.AppOpsManager")
val declaredField2 = cls.getDeclaredField("MODE_ALLOWED")
declaredField2.isAccessible = true
val checkOp =
cls.getMethod("checkOp", Integer.TYPE, Integer.TYPE, String::class.java)
val result =
checkOp.invoke(obj, 24, Binder.getCallingUid(), context.packageName) as Int
result == declaredField2.getInt(cls)
} catch (e: Exception) {
false
}
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
Settings.canDrawOverlays(context)
} else {
val appOpsMgr = context.getSystemService(Context.APP_OPS_SERVICE)
?: return false
val mode = (appOpsMgr as AppOpsManager).checkOpNoThrow(
"android:system_alert_window", Process.myUid(), context
.packageName
)
mode == AppOpsManager.MODE_ALLOWED
}
}
} - 类似的这种不能动态授权,只能引导去设置页授权的权限,还包括应用辅助功能权限android.settings.ACCESSIBILITY_SETTINGS,应用使用情况访问权限Settings.ACTION_USAGE_ACCESS_SETTINGS等。
5.辅助功能服务AccessibilityService
- AccessibilityService根据android官方介绍,设计初衷是为了帮助残障人士更好的使用app而设置的辅助功能,但是由于它过于“强大”,能够接收到前台app的各种event事件,常常被开发者用在一些特殊功能上,比如著名的微信抢红包助手,就是在accessibilityService中监听到微信红包的事件后,进行了拆红包的响应处理。
- 使用AccessibilityService,首先得自定义一个继承AcessibilityService的实现类,并onAcessibilityEvents()和onInterrupt()方法,其中,前台app的事件将通过onAcessibilityEvents()方法进行通知。
class WatchingAccessibilityService : AccessibilityService() { override fun onAccessibilityEvent(event: AccessibilityEvent) { } override fun onInterrupt() { } }
- 对Service的注册必须可不少,其中resource中指定配置文件名。
<service android:name=".WatchingAccessibilityService" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"> <intent-filter> <action android:name="android.accessibilityservice.AccessibilityService" /> </intent-filter> <meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibility" /> </service>
- 配置文件,标签为<accessibilty-service/>,用于设置一些指定的属性和限制监听的events范围,配置好后,AccessibilityService就可以使用了。
<?xml version="1.0" encoding="utf-8"?> <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:accessibilityEventTypes="typeWindowStateChanged" android:accessibilityFeedbackType="feedbackGeneric" android:accessibilityFlags="flagReportViewIds" android:canRetrieveWindowContent="true" android:description="@string/app_slogan" android:notificationTimeout="100" />
字段名 字段说明 android:packageNames 指明了自己的辅助服务关心哪些应用发出的事件,多个应用包名之间用逗号分隔,如果不填,则关注手机上所有应用发出的事件。例如只关注微信发出的事件,则这里填com.tencent.mm。 android:accessibilityEventTypes 辅助服务关注的事件类型,例如TYPE_VIEW_FOCUSED,TYPE_WINDOW_STATE_CHANGED,TYPE_NOTIFICATION_STATE_CHANGED等等。如果只关心微信的通知栏,那么这个属性可以设置为TYPE_NOTIFICATION_STATE_CHANGED。 android:accessibilityFlags 辅助服务额外的flag信息。例如FLAG_REPORT_VIEW_IDS可以使回调的事件带上view的ID。 android:accessibilityFeedbackType 事件的反馈类型,例如声音反馈、触觉反馈、视觉反馈等。 android:notificationTimeout 两个同样类型的辅助事件发给辅助服务的最小时间间隔 android:canRetrieveWindowContent 是否可以获取窗口内容 android:description 系统设置中关于app辅助功能中的描述 - 开启辅助功能,AccessibilityService具有很高的系统权限,配置好的service不会自动开启,还必须让用户在系统设置的辅助服务中开启权限才可以。这时,需要检查权限是否开启,可用下面的方法完成检查,
private fun isAccessibilitySettingsOn(): Boolean { var accessibilityEnabled = 0 val service: String = this.packageName + "/" + WatchingAccessibilityService::class.java.canonicalName try { accessibilityEnabled = Settings.Secure.getInt( applicationContext.contentResolver, Settings.Secure.ACCESSIBILITY_ENABLED ) Log.v(logTag, "accessibilityEnabled = $accessibilityEnabled") } catch (e: Settings.SettingNotFoundException) { Log.e( logTag, "Error finding setting, default accessibility to not found: " + e.message ) } val mStringColonSplitter = TextUtils.SimpleStringSplitter(':') if (accessibilityEnabled == 1) { val settingValue = Settings.Secure.getString( applicationContext.contentResolver, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES ) if (settingValue != null) { mStringColonSplitter.setString(settingValue) while (mStringColonSplitter.hasNext()) { val accessibilityService = mStringColonSplitter.next() Log.v( logTag, "-------------- > accessibilityService :: $accessibilityService $service" ) if (accessibilityService.equals(service, ignoreCase = true)) { Log.v( logTag, "We've found the correct setting - accessibility is switched on!" ) return true } } } } else { Log.v(logTag, "***ACCESSIBILITY IS DISABLED***") } return false }
如果没开启,就引导用户去设置页中开启,
val intent = Intent() intent.action = "android.settings.ACCESSIBILITY_SETTINGS" startActivity(intent) dialog.dismiss()
- 权限开启后,AccessibilityService就正常开始工作了。不过这个权限会在app每次开启的时候都需要重新去开启。比如要实现一个下载自动安装app的响应,根据“安装”文案,来匹配view,然后执行performClick即可。
@Override public void onAccessibilityEvent(AccessibilityEvent event) { super.onAccessibilityEvent(event); if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED && event.getPackageName().equals("com.android.packageinstaller")) { AccessibilityNodeInfo nodeInfo = findViewByText("安装", true); if (nodeInfo != null) { performViewClick(nodeInfo); } } }
6.访问应用数据AppUsager
- Google从 API 21 新增了接口 android.app.usage , 通过这个api让我们获取到手机中各个app的使用情况统计数据,包括进程信息、启动次数,启动时间等。
- 首先得在Manifest中声明权限,
<!-- 访问应用使用情况 --> <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions" />
- 使用UsagerStatsManager查询应用使用数据,查询时需指定时间范围,比如下面获取前台app信息的实现中,查询最近1秒钟内,ACTIVITY_RESUMED事件,可以从event中取出app的包名+activity名。
val mUsageStatsManager = getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager val now = System.currentTimeMillis() val events = mUsageStatsManager.queryEvents(now - 1000, now)//获取最近1秒的usagerStats while (events.hasNextEvent()) { val event = UsageEvents.Event() events.getNextEvent(event) when (event.eventType) { UsageEvents.Event.ACTIVITY_RESUMED -> { topActivity = "${event.packageName}\n${event.className}" } } }
- 开启权限后才可以使用,检查是否具有权限,
/** * 检查访问应用数据权限 */ fun checkUsageStatsPermissionInner(context: Context): Boolean { context.getSystemService(Context.APP_OPS_SERVICE)?.let { val appOps = it as AppOpsManager val mode = appOps.checkOpNoThrow("android:get_usage_stats",Process.myUid(), context.packageName) return mode == AppOpsManager.MODE_ALLOWED } return false }
如果发现没有权限,可以引导用户去系统设置页开启权限,
val intent = Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS) startActivityForResult(intent, requestCode)
- 那5.0以前都是怎么拿统计数据呢,事实上5.0以前更简单,不需要这么多权限,直接同AMS.getRunningTask()就可以拿到后台运行的进程,比如getRunningTask(1)就是获取前台进程。
val activityManager = applicationContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager val forGroundActivity = activityManager.getRunningTasks(1) topActivity = forGroundActivity[0].topActivity!!.packageName + "\n" + forGroundActivity[0].topActivity!!.className
7.使用adb工具dump activity
- Android提供的abd (Android debug bridge)工具是很强大的调试工具,其中adb shell dumpsys命令,可以查看Activity栈。
- 执行指令,adb shell dumpsys activity,将得到一串非常长也是非常全的一串讯息。讯息是分段展示的,为了方便查找信息,可以全局搜索“dumpsys activity”,然后分段查找。
- 其中“dumpsys activity recents”这段,打印出了当前手机后台中运行的app任务栈。
而“dumpsys activity activities”这段,会把一一罗列各个app任务的activity栈,比如下面对于美团app中的解读就可以看出,包名com.sankuai.meituan,LuancherActivity是com.meituan.android.pt.homepage.activity.MainActivity,当前栈顶activity是com.meituan.android.pt.bike.app.ui.MobikeMainActivity(美团单车),后台activity还有首页com.meituan.android.pt.homepage.activity.MainActivity。
- 在执行dumpsys命令时,也可以添加过滤参数,比如执行adb shell dumpsys activity activities,那么dump结果中就只会打印中“dumpsys activity activities”这段。
8.监听activity生命周期ActivityLifeCycleCallbacks
- Application提供的registerActivityLifecycleCallbacks()方法,允许app中所有的activity的生命周期发生变化时,给予回调。
class MainApplication extends Application { @Override public void onCreate() { super.onCreate(); registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { @Override public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {} @Override public void onActivityStarted(@NonNull Activity activity) { } @Override public void onActivityResumed(@NonNull Activity activity) { } @Override public void onActivityPaused(@NonNull Activity activity) { } @Override public void onActivityStopped(@NonNull Activity activity) { } @Override public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) { } @Override public void onActivityDestroyed(@NonNull Activity activity) { } }); }
- 源码分析,在Application中维护了一个callbacks数组,注册时,就是把ActivityLifecycleCallbacks添加进数组中,
public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) { synchronized (mActivityLifecycleCallbacks) { mActivityLifecycleCallbacks.add(callback); } }
然后,当activity的生命周期方法执行时,以Activity.onCreate()方法为例,会调用dispatchActivityCreated(),
protected void onCreate(@android.annotation.Nullable Bundle savedInstanceState) { ... dispatchActivityCreated(savedInstanceState); ... }
activity.dispatchActivityCreated()方法中,会执行Application.dispatchActivityCreated方法,
private void dispatchActivityCreated(@Nullable Bundle savedInstanceState) { getApplication().dispatchActivityCreated(this, savedInstanceState); ... }
Application.dispatchActivityCreated()方法主要就是取出callbacks数组,并遍历取出ActivityLifecycleCallbacks对象,然后一一进行回调ActivityLifecycleCallbacks.onActivityCreated()方法。
void dispatchActivityCreated(Activity activity, Bundle savedInstanceState) { Object[] callbacks = collectActivityLifecycleCallbacks(); if (callbacks != null) { for (int i=0; i<callbacks.length; i++) { ((ActivityLifecycleCallbacks)callbacks[i]).onActivityCreated(activity, savedInstanceState); } } } private Object[] collectActivityLifecycleCallbacks() { Object[] callbacks = null; synchronized (mActivityLifecycleCallbacks) { if (mActivityLifecycleCallbacks.size() > 0) { callbacks = mActivityLifecycleCallbacks.toArray(); } } return callbacks; }
- 这样做的好处在于,对于公共操作(对所有actiivty都要执行的,比如有些app的监听用户的截屏事件,然后弹窗一个反馈问题的按钮,需要对所有activity在onResume时注册ContentObserver,然后在onPause时取消注册),避免了每个activity或者在基类activity中去处理,而且往往也处理不了,因为总是有那么些activity没有继承统一的基类,比如用到的sdk里面的activity。
- 实际上Activity也提供了registerActivityLiftcycleCallbacks()方法的,如果你只是想监听某个activity的生命,比如你要提供一个sdk出去,sdk中有某个activity,你是希望开放生命周期给使用方回调的。就可以在activity中预留一个设置ActivityLifecycleCallbacks监听接口的方法。
- 与Application源码回调过程类似,activity中注册的ActivityLifecycleCallbacks回调,会被添加到mActivityLifecycleCallbacks数组中,当activity执行生命周期函数时,直接遍历数组mActivityLifecycleCallbacks,然后一一回调。
private void dispatchActivityCreated(@Nullable Bundle savedInstanceState) { getApplication().dispatchActivityCreated(this, savedInstanceState); Object[] callbacks = collectActivityLifecycleCallbacks(); if (callbacks != null) { for (int i = 0; i < callbacks.length; i++) { ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityCreated(this, savedInstanceState); } } }
9.生命周期组件Lifecycle源码解析
- Lifecycle组件库作为Jetpack的重要一员,用于感知Activity和Fragment的生命周期。
- 先看用法,首先要建一个继承自LifecycleObserver的观测类,在类中定义各个生命周期方法,方法需要用@LifecycleEvent注解标识。然后在Activity或Fragment中,将其添加到LifecycleRegister中,
class HomeLifecycleObserver : LifecycleObserver { private val logTag = "HomeActivityObserver" @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) fun onActivityCreate() { Log.d(logTag, "onActivityCreate") } @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) fun onActivityResume() { Log.d(logTag, "onActivityResume") } }
override fun onCreate(savedInstanceState: Bundle?) { lifecycle.addObserver(HomeLifecycleObserver()) super.onCreate(savedInstanceState) }
然后,当activity的执行onCreate()时,就会调用HomeLifecycleObserver的注解类型为Life.Event.ON_CREATE的事件方法,同理,当activity的执行onResume()时,就会调用HomeLifecycleObserver的注解类型为Life.Event.ON_RESUME的事件方法。
- 剖析源码,首先看添加Observer的方法,ComponentActivity类中初始化类一个lifecycleRegistry对象,调用lifecycleRegistry.addObserver()方法自定义的LifecycleObserver对象,
public Lifecycle getLifecycle() { return mLifecycleRegistry; }
private final LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);
public LifecycleRegistry(@NonNull LifecycleOwner provider) {
mLifecycleOwner = new WeakReference<>(provider);
mState = INITIALIZED;
}@Override public void addObserver(@NonNull LifecycleObserver observer) { Lifecycle.State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED; LifecycleRegistry.ObserverWithState statefulObserver = new LifecycleRegistry.ObserverWithState(observer, initialState); LifecycleRegistry.ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver); ... }
添加的核心逻辑就是把传入的Observer对象存放到mObserverMap中,其中key = observer本身,value = LifecycleRegistry.ObserverWithState对象,这个对象非常重要,在后面会详细说,
- 在ComponentActivity的onCreate()方法中,有对Lifecycle非常关键的一句话,ReportFragment.injectIfNeedIn(),
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); mSavedStateRegistryController.performRestore(savedInstanceState); ReportFragment.injectIfNeededIn(this); if (mContentLayoutId != 0) { setContentView(mContentLayoutId); } }
这句话主要是向Activity中添加一个无UI的ReportFragment,
public static void injectIfNeededIn(Activity activity) { // ProcessLifecycleOwner should always correctly work and some activities may not extend // FragmentActivity from support lib, so we use framework fragments for activities android.app.FragmentManager manager = activity.getFragmentManager(); if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) { manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit(); // Hopefully, we are the first to make a transaction. manager.executePendingTransactions(); } }
Lifecycler感知生命周期的回调入口正是这个ReportFragment在其生命周期的各个阶段发起的,
@Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); dispatchCreate(mProcessListener); dispatch(Lifecycle.Event.ON_CREATE); } @Override public void onStart() { super.onStart(); dispatchStart(mProcessListener); dispatch(Lifecycle.Event.ON_START); } @Override public void onResume() { super.onResume(); dispatchResume(mProcessListener); dispatch(Lifecycle.Event.ON_RESUME); } @Override public void onPause() { super.onPause(); dispatch(Lifecycle.Event.ON_PAUSE); } @Override public void onStop() { super.onStop(); dispatch(Lifecycle.Event.ON_STOP); } @Override public void onDestroy() { super.onDestroy(); dispatch(Lifecycle.Event.ON_DESTROY); // just want to be sure that we won't leak reference to an activity mProcessListener = null; }
- 从ReportFragment.dispatch()方法,分析生命周期事件的分发,dispatch方法的源码如下,因为ComponentActivity实现了LifecycleOwner接口,而且前面也分析了ComponentActivity中的lifecycle就是LifecyclerRegistry对象的实例,因此,方法会进入LifecycleRegistry.handleLifecycleEvent(event)方法,
private void dispatch(Lifecycle.Event event) { Activity activity = getActivity(); if (activity instanceof LifecycleRegistryOwner) { ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event); return; } if (activity instanceof LifecycleOwner) { Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle(); if (lifecycle instanceof LifecycleRegistry) { ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event); } } }
handleLifecycleEvent方法进行一系列处理后,进入sync()
public void handleLifecycleEvent(@NonNull Lifecycle.Event event) { State next = getStateAfter(event); moveToState(next); } private void moveToState(State next) { if (mState == next) { return; } mState = next; if (mHandlingEvent || mAddingObserverCounter != 0) { mNewEventOccurred = true; // we will figure out what to do on upper level. return; } mHandlingEvent = true; sync(); mHandlingEvent = false; }
sync()方法里,不管走到backwardPass()还是forwadPass(),
private void sync() { LifecycleOwner lifecycleOwner = mLifecycleOwner.get(); if (lifecycleOwner == null) { throw new IllegalStateException("LifecycleOwner of this LifecycleRegistry is already" + "garbage collected. It is too late to change lifecycle state."); } while (!isSynced()) { mNewEventOccurred = false; // no need to check eldest for nullability, because isSynced does it for us. if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) { backwardPass(lifecycleOwner); } Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest(); if (!mNewEventOccurred && newest != null && mState.compareTo(newest.getValue().mState) > 0) { forwardPass(lifecycleOwner); } } mNewEventOccurred = false; }
都将执行observer.dispatchEvent()方法,这就是Observer里定义的生命周期方法的回调真正入口了。
private void forwardPass(LifecycleOwner lifecycleOwner) { Iterator<Entry<LifecycleObserver, ObserverWithState>> ascendingIterator = mObserverMap.iteratorWithAdditions(); while (ascendingIterator.hasNext() && !mNewEventOccurred) { Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next(); ObserverWithState observer = entry.getValue(); while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred && mObserverMap.contains(entry.getKey()))) { pushParentState(observer.mState); observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState)); popParentState(); } } } private void backwardPass(LifecycleOwner lifecycleOwner) { Iterator<Entry<LifecycleObserver, ObserverWithState>> descendingIterator = mObserverMap.descendingIterator(); while (descendingIterator.hasNext() && !mNewEventOccurred) { Entry<LifecycleObserver, ObserverWithState> entry = descendingIterator.next(); ObserverWithState observer = entry.getValue(); while ((observer.mState.compareTo(mState) > 0 && !mNewEventOccurred && mObserverMap.contains(entry.getKey()))) { Event event = downEvent(observer.mState); pushParentState(getStateAfter(event)); observer.dispatchEvent(lifecycleOwner, event); popParentState(); } } }
- 还记得前面说的LifecycleRegistry.ObserverWithState对象吗,静态内部类ObserverWithState的源码如下,
static class ObserverWithState { State mState; LifecycleEventObserver mLifecycleObserver; ObserverWithState(LifecycleObserver observer, State initialState) { mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer); mState = initialState; } void dispatchEvent(LifecycleOwner owner, Event event) { State newState = getStateAfter(event); mState = min(mState, newState); mLifecycleObserver.onStateChanged(owner, event); mState = newState; } }
上面已经分析到,自定义的Observer生命周期方法,最终是通过ObserverWithState.dispatchEvent()下发的,而这个方法中,又把事件转给了mLifecycleObserver.onStateChanged()去处理,这里有牵扯进来一个非常重要的LifecycleEventObserver对象mLifecycleObserver,它通过Lifecling.lifecycleEventObserver()获得,这个方法玄机很大,得先说了才行。
- Lifecling.lifecycleEventObserver()里面判断逻辑很多的,但就当前我们自定义LifecycleObserver类的注解方法的方式,最终返回的是new ReflectGenericLifecyclerObserver()对象。
@NonNull static LifecycleEventObserver lifecycleEventObserver(Object object) { boolean isLifecycleEventObserver = object instanceof LifecycleEventObserver; boolean isFullLifecycleObserver = object instanceof FullLifecycleObserver; if (isLifecycleEventObserver && isFullLifecycleObserver) { return new FullLifecycleObserverAdapter((FullLifecycleObserver) object, (LifecycleEventObserver) object); } if (isFullLifecycleObserver) { return new FullLifecycleObserverAdapter((FullLifecycleObserver) object, null); } if (isLifecycleEventObserver) { return (LifecycleEventObserver) object; } final Class<?> klass = object.getClass(); int type = getObserverConstructorType(klass); if (type == GENERATED_CALLBACK) { List<Constructor<? extends GeneratedAdapter>> constructors = sClassToAdapters.get(klass); if (constructors.size() == 1) { GeneratedAdapter generatedAdapter = createGeneratedAdapter( constructors.get(0), object); return new SingleGeneratedAdapterObserver(generatedAdapter); } GeneratedAdapter[] adapters = new GeneratedAdapter[constructors.size()]; for (int i = 0; i < constructors.size(); i++) { adapters[i] = createGeneratedAdapter(constructors.get(i), object); } return new CompositeGeneratedAdaptersObserver(adapters); } return new ReflectiveGenericLifecycleObserver(object); }
private static int getObserverConstructorType(Class<?> klass) { Integer callbackCache = sCallbackCache.get(klass); if (callbackCache != null) { return callbackCache; } int type = resolveObserverCallbackType(klass); sCallbackCache.put(klass, type); return type; }
private static int resolveObserverCallbackType(Class<?> klass) { // anonymous class bug:35073837 if (klass.getCanonicalName() == null) { return REFLECTIVE_CALLBACK; } Constructor<? extends GeneratedAdapter> constructor = generatedConstructor(klass); if (constructor != null) { sClassToAdapters.put(klass, Collections .<Constructor<? extends GeneratedAdapter>>singletonList(constructor)); return GENERATED_CALLBACK; } boolean hasLifecycleMethods = ClassesInfoCache.sInstance.hasLifecycleMethods(klass); if (hasLifecycleMethods) { return REFLECTIVE_CALLBACK; } ... }
看看ReflectGenericLifecyclerObserver这个类的源码,可以明确一个重要结论就是:自定义注解生命周期方法,通过ObserverWithState.dispatchEvent()转交给LifecycleEventObserver.onStateChanged()方法去处理,而这里从Lifecling.lifecycleEventObserver()得到LifecycleEventObserve实现类是ReflectGenericLifecyclerObserver,从而ObserverWithState.dispatchEvent()实际把事件转交给了ReflectGenericLifecyclerObserver.onStateChange()方法。
class ReflectiveGenericLifecycleObserver implements LifecycleEventObserver { private final Object mWrapped; private final CallbackInfo mInfo; ReflectiveGenericLifecycleObserver(Object wrapped) { mWrapped = wrapped; mInfo = ClassesInfoCache.sInstance.getInfo(mWrapped.getClass()); } @Override public void onStateChanged(LifecycleOwner source, Event event) { mInfo.invokeCallbacks(source, event, mWrapped); } }
- 分析ReflectGenericLifecyclerObserver.onStateChange()方法,这里面就干了一件事,回调CallbackInfo对象的invokeCallbacks()方法,那就先看看这个CallbackInfo对象把,
CallbackInfo getInfo(Class klass) { CallbackInfo existing = mCallbackMap.get(klass); if (existing != null) { return existing; } existing = createInfo(klass, null); return existing; }
private CallbackInfo createInfo(Class klass, @Nullable Method[] declaredMethods) { ... Map<MethodReference,Lifecycle.Event> handlerToEvent = new HashMap(); Method[] methods = declaredMethods != null ? declaredMethods : getDeclaredMethods(klass); boolean hasLifecycleMethods = false; for (Method method : methods) { OnLifecycleEvent annotation = method.getAnnotation(OnLifecycleEvent.class); if (annotation == null) { continue; } hasLifecycleMethods = true; ... Lifecycle.Event event = annotation.value(); ... MethodReference methodReference = new MethodReference(callType, method); verifyAndPutHandler(handlerToEvent, methodReference, event, klass); } CallbackInfo info = new CallbackInfo(handlerToEvent); mCallbackMap.put(klass, info); mHasLifecycleMethods.put(klass, hasLifecycleMethods); return info; }
private void verifyAndPutHandler(Map<MethodReference, Lifecycle.Event> handlers, MethodReference newHandler, Lifecycle.Event newEvent, Class klass) { Lifecycle.Event event = handlers.get(newHandler); ...if (event == null) { handlers.put(newHandler, newEvent); } }
这里干了一件很重要的事情,遍历自定义的LifecycleObserver类中方法,筛选出其中被OnLifecylerEvent注解过的那些方法,并将方法和方法的注解事件类型作为key-value添加到HashMap中,然后用这个HashMap构建出CallbackInfo对象,最后以key = callbackInfo, value = overserClass将其添加进一个Map中。
CallbackInfo(Map<MethodReference, Lifecycle.Event> handlerToEvent) { mHandlerToEvent = handlerToEvent; mEventToHandlers = new HashMap<>(); for (Map.Entry<MethodReference, Lifecycle.Event> entry : handlerToEvent.entrySet()) { Lifecycle.Event event = entry.getValue(); List<MethodReference> methodReferences = mEventToHandlers.get(event); if (methodReferences == null) { methodReferences = new ArrayList<>(); mEventToHandlers.put(event, methodReferences); } methodReferences.add(entry.getKey()); } }
- 现在可以看"mInfo.invokeCallbacks()"这句了,前面都是些从Map中根据key取出value的“废话”,重要的是看取出来的MethodReference执行invokeCallback()方法的过程,
void invokeCallbacks(LifecycleOwner source, Lifecycle.Event event, Object target) { invokeMethodsForEvent(mEventToHandlers.get(event), source, event, target); invokeMethodsForEvent(mEventToHandlers.get(Lifecycle.Event.ON_ANY), source, event, target); }
private static void invokeMethodsForEvent(List<MethodReference> handlers, LifecycleOwner source, Lifecycle.Event event, Object mWrapped) { if (handlers != null) { for (int i = handlers.size() - 1; i >= 0; i--) { handlers.get(i).invokeCallback(source, event, mWrapped); } } }
- 终于水落石出了,MethodReference.invokeCallback()里就清晰多了,直接拿mMethod.invoke()执行了,反射执行了我们自定义的注解方法。
static class MethodReference { final int mCallType; final Method mMethod; MethodReference(int callType, Method method) { mCallType = callType; mMethod = method; mMethod.setAccessible(true); } void invokeCallback(LifecycleOwner source, Lifecycle.Event event, Object target) { //noinspection TryWithIdenticalCatches try { switch (mCallType) { case CALL_TYPE_NO_ARG: mMethod.invoke(target); break; case CALL_TYPE_PROVIDER: mMethod.invoke(target, source); break; case CALL_TYPE_PROVIDER_WITH_EVENT: mMethod.invoke(target, source, event); break; } } catch (InvocationTargetException e) { throw new RuntimeException("Failed to call observer method", e.getCause()); } catch (IllegalAccessException e) { throw new RuntimeException(e); } }
... }
10.匿名内部类导致的内存泄漏
- 注册接口造成时创建匿名内部类,一个典型的例子:在activity开启一个回调监听,setCallback()执行时,创建了ICallback接口的匿名内部实现类,然后等待外部回到success()方法。
titleTv.setOnClickListener { Log.d(logTag, "开始计时") val time = 10 fragment.setCallback(time, object : ICallback { override fun success() { Log.d(logTag, "计时${time}秒时间已到!!") } }) }
- 一旦监听里执行了耗时任务,导致success()的回调很晚,比如下面模拟了一个计时任务的回调,
fun setCallback(millTime: Int, callback: ICallback) { //模拟耗时任务 Thread(Runnable { var i = 0 var currentTime = System.currentTimeMillis() while (i < millTime) { if (System.currentTimeMillis() - currentTime >= 1000) { i++ updateTime(i) currentTime = System.currentTimeMillis() Log.d(TAG, "当前计时${i}秒") } } callback.success() }).start() }
就有可能发生,success()在activity.onDestroy()之后才执行的情况,而此时activity因为持有ICallback匿名内部实现类的引用,内部得不到及时回收,从而发生了内存泄漏。
- 因此,对于任何可能发生在activity destroy之后的监听,都应该在onDestroy执行之前,取消监听,like this,
override fun onDestroy() { super.onDestroy() fragment.setCallback(0, null) Log.d(logTag, "计时UI onDestroy") }
置null后,此前创建的匿名内部类与activity之间解除了引用关联。
- 其实,在了解了lifecycle之后,unRegister的操作也可以借助lifecycle进行,设置外部监听时的同时,将actiivty传入到监听现场,同时给activity添加LifecycleObserver观察activity生命周期,当Event.ON_DESTORY事件发生时,执行取消监听的操作。这样做的好处时,设置监听的同时就准备好了取消监听的操作,取消监听直观地在监听现场发生。
private var mCallback: ICallback? = null fun setCallback(millTime: Int, callback: ICallback, activity: LeakTestActivity) { mCallback = callback activity.lifecycle.addObserver(object : LifecycleObserver { @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) fun onActivityDestroy() { mCallback = null } }) //模拟耗时任务 Thread(Runnable { var i = 0 var currentTime = System.currentTimeMillis() while (i < millTime) { if (System.currentTimeMillis() - currentTime >= 1000) { i++ updateTime(i) currentTime = System.currentTimeMillis() Log.d("zouhecan", "当前计时${i}秒") } } mCallback?.success() }).start() }
下一篇:android日记(七)