Exposure

Project Url: wp529/Exposure
Introduction: ExposureRecyclerView 是一个很方便对 RecyclerView 的 item 进行曝光埋点的库,在现有代码上少量侵入即可实现 RV 的曝光埋点。支持 RV 的线性布局、网格布局、瀑布流布局,横向滑动曝光埋点。支持配置 item 的有效曝光面积。
More: Author   ReportBugs   
Tags:

Exposure

Exposure 是一个很方便对 View 进行曝光埋点收集的库,不用修改现有布局实现方式,只需在现有代码上做极少量修改即可实现 View 的曝光埋点。支持判断 View 是否达到有效曝光面积,支持 RecyclerView 的线性布局、网格布局、瀑布流布局,横向滑动曝光埋点,支持对指定 View 进行曝光收集。

添加依赖:

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}
dependencies {
    implementation 'com.github.wp529:Exposure:1.2.4'
}
使用方式:
  1. 将需要采集曝光的 View 替换为对应的曝光 View,库里面提供了三个曝光 View (ExposureLinearLayout,ExposureFrameLayout,ExposureRelativeLayout),若需其他类型的曝光 View 可以自行让对应 View 实现 IProvideExposureData 接口

    <?xml version="1.0" encoding="utf-8"?>
    <com.wp.exposure.view.ExposureFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/exposureRoot"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <TextView
            android:id="@+id/tvText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            tools:text="TEXT" />
    </com.wp.exposure.view.ExposureLinearLayout>
    
  2. 为曝光 View 绑定上对应的曝光数据

    //注:这里的 data 对象最好实现了 equals 方法
    exposureRoot.exposureBindData = data
    

以下两种方式根据布局方式选择其一

RecyclerView 添加曝光收集

在给 RecyclerView 设置完 adapter 后实例化 RecyclerViewExposureHelper,必须在设置完 adapter 后才能实例化的原因是为了能让 RecyclerViewExposureHelper 在 adapter 调用更新 item 方法后可以自动计算曝光数据。实例化时需传递五个参数

  • recyclerView 需要收集曝光的 RecyclerView
  • exposureValidAreaPercent 判定曝光的面积,即大于这个面积才算做曝光,百分制,eg:设置为 50 item 的面积为 200 平方,则必须要展示 200 * 50% = 100 平方及以上才算为曝光
  • lifecycleOwner RecyclerView 感知此生命周期组件,根据生命周期感知 RV 可见性,以便自动处理开始曝光和结束曝光,一般情况 RV 在 Activity 中传 Activity,在 Fragment 中传 Fragment
  • mayBeCoveredViewList 可能会遮挡 RV 的 View 集合
  • exposureStateChangeListener 曝光状态改变监听器
     recyclerViewExposureHelper =
              RecyclerViewExposureHelper(
                  recyclerView = rvList,
                  exposureValidAreaPercent = 50,
                  lifecycleOwner = this,
                  mayBeCoveredViewList = null,
                  exposureStateChangeListener = object : IExposureStateChangeListener<String> {
                      override fun onExposureStateChange(
                          bindExposureData: String,
                          position: Int,
                          inExposure: Boolean
                      ) {
                          Log.i(
                              "ListActivity", "${bindExposureData}${
                                  if (inExposure) {
                                      "开始曝光"
                                  } else {
                                      "结束曝光"
                                  }
                              }"
                          )
                      }
                  }
              )
    
    其他情况:若 RecyclerView 被嵌套在可滚动控件(eg:ScrollView,NestedScrollView,RecyclerView 等)中,将会导致 RecyclerViewExposureHelper 中持有的 RecyclerView 不能响应滑动的情况,就必须由外部告知 RecyclerView 滚动状态然后触发曝光收集。具体做法:给可滚动控件添加滚动监听,滚动监听中调用 recyclerViewExposureHelper.onScroll()

对指定 View 添加曝光收集

实例化 ViewExposureHelper,实例化时需传递五个参数,与 RecyclerViewExposureHelper 基本一致

  • viewList 需要指定收集曝光的 View 集合

        val helper = ViewExposureHelper(
              viewList = list,
              exposureValidAreaPercent = 50,
              lifecycleOwner = this,
              mayBeCoveredViewList = null,
              exposureStateChangeListener = object : IExposureStateChangeListener<String> {
                  @SuppressLint("LongLogTag")
                  override fun onExposureStateChange(
                      bindExposureData: String,
                      position: Int,
                      inExposure: Boolean
                  ) {
                      Log.i(
                          "CollectViewGroupActivity", "${bindExposureData}${
                              if (inExposure) {
                                  "开始曝光"
                              } else {
                                  "结束曝光"
                              }
                          }"
                      )
                  }
              }
          )
    

1.若指定收集曝光的 View 在可滚动的布局中,那么在滚动时,需调用 helper.onScroll()

2.若指定收集曝光的 View Visible 状态变更,helper.childViewVisibleChange()

3.若需动态添加指定收集曝光的 View,则需调用 helper.addViewToRecordExposure(view)


至此,曝光收集接入完成,只需在onExposureStateChange回调中进行处理即可。onExposureStateChange回调会回传三个参数。

  1. view 绑定的曝光数据
  2. 曝光状态改变的位置
  3. 曝光状态。曝光状态 true 代表 view 从未曝光状态进入曝光中状态,false 代表 view 从曝光中状态进入结束曝光状态

View 曝光埋点对客户端来说只用处理三个问题,此库的作用即是处理这三个问题

  • view 可见(开始曝光)

  • view 不可见(结束曝光)

  • view 可见面积是否为有效曝光面积

埋点 SDK 一般会提供三个 api 供客户端调用

  • onItemExposureStart()

  • onItemExposureEnd()

  • onItemExposureUpload()

所以只需在onExposureStateChange里调用埋点 SDK 对应的 api 即可,至于曝光时长是否为有效曝光一般由埋点 SDK 进行计算

若没有埋点 SDK,也可通过onExposureStateChange自行处理相关逻辑

可查看 demo 获知更多使用姿势
Apps
About Me
GitHub: Trinea
Facebook: Dev Tools