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路径下,执行,
    1. chmod u+x d2j_invoke.sh
    2. chmod u+x d2j-dex2jar.sh
    3. 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日记(七)

 

posted @ 2020-09-05 17:08  是个写代码的  阅读(305)  评论(0编辑  收藏  举报