美团点评无埋点方案 - 利用 AppCompatDetegale 替换控件 | 掘金技术征文

版权声明:android

本帐号发布文章均来自公众号,承香墨影(cxmyDev),版权归承香墨影全部。app

未经容许,不得转载。post

1、前言

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

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

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

2、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 。code

AppCompatActivity 其实内部的实现原理也和以前的 ActionBarActivity 实现不一样,它是经过是经过 AppCompatDelegate 来实现的。AppCompatActivity 将全部的生命周期相关的会掉,都交由 AppCompatDelegate 来处理。cdn

可是实际是他们并无直接的关联关系,咱们也能够直接使用 AppCompatDelegate 来放入咱们本身实现的 Activity 中,可是这样就会更麻烦,通常也不推荐这样使用。对象

一、AppCompat为何而存在

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

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

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

二、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 控件了。

3、举个例子

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

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

再实现一个咱们本身的 AppCompatDelegate 。

而后本身定一个 AppCompatDelegate 根据类,用于返回 AppCompatDelegate,这里只是作演示,因此直接返回上面定义的 AppCompatDelegate 类了。

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

运行以后,从输出Log中能够看到咱们须要的内容。

4、回到主要的话题

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

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

5、结语

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

那咱们敬请期待吧。

本文参加掘金技术征文:juejin.im/post/58d8e9…

公众号二维码.jpg
相关文章
相关标签/搜索