美团点评无埋点方案-利用AppCompatDetegale替换控件

版权声明:

本公众号发布的所有文章,均属于原创,版权归本公众号所有。

未经允许,不得转载。

一、前言

前面在公众号里的文章中讲到,美团的无埋点方案就是,重写所有的 UI 控件,然后对其事件进行代理监听,最终在触发事件的时候,去判断是否需要对此次事件进行统计点的上报。所以引发出,如何低成本的替换掉已有项目内的 UI 控件。

两个方案,其中一个是借鉴 Android v7 支持的思路,通过 AppCompatDelegate 代理,来自动替换我们需要的 UI 控件。

今天主要就这个主题,进行讲解。

二、v7 的代理思路

说到 Android support v7 包内的代理思路,是通过 AppCompatDelegate 来实现的。

AppCompat 在最开始出现在 v7 包中的时候,其实作用非常的小,只是为了让 API level 7+ 的设备,也可以使用 ActionBar 。而在 Support v7:21 版本之后,AppCompat 承担了跟多的责任,可以为 API Level 7+ 的设备带来 Material Color Palette 、Widget 着色、ToolBar 等功能。而且之前推荐使用的 ActionBarActivity 也不再推荐使用,取而代之的是 AppCompatActivity 。

AppCompatActivity 其实内部的实现原理也和之前的 ActionBarActivity 实现不同,它是通过是通过 AppCompatDelegate 来实现的。AppCompatActivity 将所有的生命周期相关的会掉,都交由 AppCompatDelegate 来处理。

但是实际是他们并没有直接的关联关系,我们也可以直接使用 AppCompatDelegate 来放入我们自己实现的 Activity 中,但是这样就会更麻烦,一般也不推荐这样使用。

1、AppCompat为什么而存在

AppCompat 为了支持 MD 的效果,需要其内部的控件都具有自动着色功能,这样可以保持 App 在设计上具有一致的体验和提高认可度。而这些是原本的 UI 控件所不具备的,所以它只好将其需要的 UI 控件全部重写一遍来支持这个效果。

这些被重写的 UI 控件,都在 android.support.v7.widget 包下面:

可以看到这些被重写的 UI 控件都是 AppCompat 开头的,但是如果重写了这么多控件,现有项目直接硬替换起来,工作量就会非常大,所以 AppCompatDelegate 这种以代理的方式自动为我们替换所使用的 UI 控件的功能就非常的有必要了。

2、AppCompatDelegate 是如何工作的

在 AppCompatActivity 中,使用 getDelegate() 方法来获得 AppCompatDelegate 对象的。

而这个 AppCompatDelegate.create() 方法就是其做代理支持的实现。

可以看到它除了对 Activity 有支持之外,还对 Dialog 也有支持。并且在其中,分别根据不同的 API Level 进行不同的实现,而且最低能支持到 API Level 9。

虽然这里看到它通过 API Level 做了区分判断来做具体的实现,但是类似这种 AppCompatDelegateImplVxx 的类,都高版本的继承低版本的。而 AppCompatDelegateImplV9 中,就是通过 LayoutInflaterFactory 接口来实现 UI 控件替换的代理。

在解析 ViewTree 的时候,会调用 createView() 方法来得到 View 对象,而在其中,又是通过 mAppCompatViewInFlater.createView() 来真实的获取 View 的。

而在 mAppCompatViewInFlater.createView() 中,就是通过 UI 控件的名称,来替换掉我们需要的 AppCompat 的 UI 控件。

所以到这里,就可以发现,如果我们也需要利用 AppCompatDelegate 来替换掉我们需要的 UI 控件,只需要自己实现一个 AppCompatDelegate 以及其中的 callActivityOnCreateView() 方法。在实际使用的 AppCompatActivity 的父类中,重写 getDelegate 方法,将方法的返回值替换成我们之前修改过的 AppCompatDelegate ,就可以实现自动替换 UI 控件了。

三、举个例子

写到这里,自然是要举个例子来说明问题。

首先我们重写一个 Button 控件,对其中的 onClick 事件做一个代理监听。

再实现一个我们自己的 AppCompatDelegate 。

然后自己定一个 AppCompatDelegate 根据类,用于返回 AppCompatDelegate,这里只是做演示,所以直接返回上面定义的 AppCompatDelegate 类了。

最终,在使用的 Activity 中,重写 getDelegate() 方法,做到替换。

运行之后,从输出Log中可以看到我们需要的内容。

四、回到主要的话题

在回到我们需要做无埋点统计的方案内的话题中,实际上,我们需要的是用他来替换掉我们重写后的控件。而使用 AppCompatDelegate 的方案,只能重写我们自己使用的 UI 控件,无法替换掉第三方库中重写的 UI 控件。

虽然我们知道有这么个缺陷,但是实际上,在项目内用到第三方库中的 UI 控件的场景毕竟是有限的,我们只需要在使用之前对其进行再封装,或者对这些使用第三方库的 UI 控件的位置,严格保证不遗漏统计点,这样的方案也是可以被我们接受的。

五、结语

下一篇再讲解一下如何通过 Gradle 插件的形式,在编译期间,替换掉三方库内的 UI 控件。

那我们敬请期待吧。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值