Androidv7支持库声明式埋点的思路是什么?

优采云 发布时间: 2021-02-10 08:00

  Androidv7支持库声明式埋点的思路是什么?

  声明性嵌入的想法是使嵌入代码与特定的交互和业务逻辑脱钩。开发人员只需关心需要嵌入的控件,并声明这些控件所需的嵌入数据,从而降低掩埋点的成本。

  Android

  在Android中,我们自定义了常用的UI控件,例如TextView,LinearLayout,ListView,ViewPager等,并重写了事件响应方法,并自动在这些方法中填充嵌入式代码。重写控件的优点是可以拦截更多事件,执行效率高并且操作稳定。但是它的缺点也很明显-移植成本很高!

  为了解决这个问题,我们从Android v7支持库的想法中学到了,该库通过AppCompatDelegate代理自动替换UI控件。

  public class GAAppCompatDelegateV14 extends AppCompatDelegateImplV14 {

@Override

View callActivityOnCreateView(View parent, String name, Context context, AttributeSet attrs) {

switch (name) {

case "TextView":

return new NovaTextView(context, attrs);

}

return super.callActivityOnCreateView(parent, name, context, attrs);

}

}

  通过这种方式,开发人员只需要在其Activity基类中重写getDelegate方法,用修改后的AppCompatDelegate替换该方法的返回值,然后自动替换UI控件。

  @Override

public AppCompatDelegate getDelegate() {

if (mDelegate == null) {

mDelegate = GAAppCompatUtil.create(this, this);

}

return mDelegate;

}

  但是,出现了新问题。

  如果在引用的第三方库中重写了UI控件,则上述方法将不会生效,这意味着我们需要一种方法来替换UI控件类的父类。但是,在运行时,我们找不到替换UI控件类的父类的可行方法。因此,我们尝试在编译时修改父类,并开发了Gradle插件。实际上,这样做没有运行时效率问题,但是会牺牲一些编译速度。这样,开发人员只需运行此插件即可用我们重写的UI控件自动替换UI控件的父类。

  apply plugin: 'com.meituan.judasplugin'

  使用声明性埋入点后,只需在初始化控件时声明所需的埋入点。我们不再需要入侵该程序的各种响应功能,从而减少了掩埋点的难度。

  GAHelper.bindClick(view, bid, lab);

  iOS

  在iOS中,通过使用与Objective-C相关的属性和类别的语法特征,我们无需重写UI控件就可以实现声明式管理。对于UIControl,您可以在声明掩埋点时添加一个新操作,并在事件发生时自动填写掩埋代码。

  - (void)nvja_setAnalyticsParams:(NVJAMGEParameter *)params mgeType:(SAKStatisticsEventMGEType)type

{

if (self.wmja_clickParams == nil && type == SAKStatisticsEventClick) {

[self addTarget:self action:@selector(wmja_controlDidTapped:) forControlEvents:UIControlEventTouchUpInside];

}

[super nvja_setAnalyticsParams:params mgeType:type];

}

  对于UITableView,您可以重写UITableViewDelegate,使用消息传递机制来拦截事件,并自动在事件回调方法中填充掩埋的代码。

  - (void)forwardInvocation:(NSInvocation *)anInvocation

{

SEL selector = [anInvocation selector];

if (self.originalDelegate && [self.originalDelegate respondsToSelector:selector]) {

[anInvocation invokeWithTarget:self.originalDelegate];

}

SEL nvjaSelector = [self nvjaSelector:selector];

if ([super respondsToSelector:nvjaSelector]) {

[anInvocation setSelector:nvjaSelector];

[anInvocation invokeWithTarget:self];

}

}

  类似地,在使用声明性嵌入方法之后,嵌入代码得到了简化。

  NVJAMGEParameter *parameter = [[NVJAMGEParameter alloc] init];

parameter.bid = @"bid";

parameter.lab = @{@"poi_id":@"1"};

button.nvja_clickParams = parameter;

  声明性嵌入可以代替所有代码嵌入,并可以解决早期阶段移植成本高的问题。但这本质上是一种代码埋入点,但是代码埋入点减少了,并且不再入侵业务逻辑。如果要满足动态部署和修复嵌入式点的需求,则需要完全消除写在前端的嵌入式代码。

  无痕埋点

  我们注意到,声明式埋入点需要进行硬编码的主要原因有两个:第一是需要声明埋入点控件的唯一事件标识符,即bid;第二个是需要将某些业务字段放入前端埋藏时携带,这些字段是只能在运行时知道的值。

  首先,我们可以尝试使用一致的规则在前端和后端自动生成事件标识符,以便后端可以配置前端的埋入行为以实现自动埋入。对于第二点,您可以尝试以某种方式自动将业务数据与掩埋点数据相关联。这种关联可以发生在前端或后端。

  事件ID

  为了自动生成事件标识符,我们需要获取每个控件自己的父组件的ID,类名和索引以及其他特征信息,然后向上遍历以找到根节点。根节点通常是手动标记的。如果没有标记,则默认情况下它是视图层次结构树的顶部节点。最后,将遍历生成的路径上所有节点的特征信息组合在一起,这是该事件的标识。考虑到实际布局中可能有一些动态插入的控件,我们允许父组件的索引中存在一定的错误。

  配置背景需要维护自动生成的事件标识符和投标映射关系,并且可以将配置文件发布到前端。触发前端控制事件后,将自动匹配配置文件以获取相应的出价。应该注意的是,配置后台维护事件标识并非易事。主要的复杂性在于由不同版本之间的布局更改引起的事件标识更改。这就是为什么需要手动标记根节点的原因。因此,通常我们会选择不容易更改的视图节点。

  

  数据关联

  为了实现业务数据和掩埋点数据之间的自动关联,我们首先尝试了前端和后端日志关联方法。也就是说,当前端请求后端API时,后端会将业务数据写入日志,并在数据清理期间最终合并相应的前端日志和后端日志。这种方法的问题是后端重建的成本很高,并且数据清理的成本很大,因此无法广泛使用。但是在某些特殊情况下,例如,某些业务数据只能由后端知道,而前端则不知道,这种关联是必要的。

  更常见的数据关联发生在前端数据之间。当页面跳转时,通过规范的跳转URI方案将业务数据传递到下一页,并自动将其填充到该页面的PV事件中。此页面中生成的所有其他事件将携带与PV事件相同的业务数据。

  通过这种方式,通过自动生成事件标识符并执行数据关联,我们可以实现“无痕掩埋”,并且可以通过配置文件动态发出掩埋节点,从而具有动态部署和修复掩埋点的能力。但是,应该注意的是,这种“无痕埋点”并不能解决所有问题。当无法通过数据关联获得业务领域时(这种情况更为常见),仍然需要开发人员代码埋入点或声明性埋入点指定。根据当前实践阶段的数据,通过无缝掩埋可以解决业务中约70%的掩埋需求,而对于其余30%的掩埋需求,仍然需要声明性掩埋和代码掩埋。

  摘要

  前端数据采集和报告是构建数据平台过程中最重要的链接。美团点评的前端每天都会报告数百亿次数据。为了更好地满足公司各种业务中对嵌入点日益复杂的要求,以及嵌入点的准确性,及时性和开发效率,我们基于代码嵌入方案开发了一套轻量级的声明性方法。公司的前端掩埋方案,以及在动态掩埋和无缝掩埋方向上的进一步探索和实践。目前,声明性掩埋点已在某些企业中得到充分使用。从数据质量和开发人员反馈的角度来看,已经实现了预期的收益。非标记掩埋点也在一些业务中得到验证和不断优化,并将在以后在公司内部进一步推广。

  在实践中,我们意识到掩埋点的问题无法通过单一的技术解决方案来解决。我们需要在不同的情况下选择不同的掩埋方案。例如,对于简单的用户行为事件,可以使用非标记掩埋点来解决;对于需要携带大量可以在运行时学习的业务领域的业务领域的埋入要求,需要使用声明性埋入点来解决它们。从更高的角度来看,除了优化前端埋入技术之外,埋入数据的标准化,前端和后端协作埋入,数据清理和关联对于构建更自动化和动态的埋入系统也非常重要。将来。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线