Fresco 源码解析 - 利用 @DoNotSkip 来防止混淆

Posted 我是老梁

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Fresco 源码解析 - 利用 @DoNotSkip 来防止混淆相关的知识,希望对你有一定的参考价值。

我们都知道,如果打开了混淆开关,代码 release 阶段会根据 proguard 规则进行混淆,但是有些实体类(例如 json 字符串对应的 model)需要进行序列化、反序列化,而序列化工具(例如 Gson、fastjson)是利用反射来一一对应 json 串的 key 和实体类的成员变量。

例如,我们定义一个 POJO 类型的 User 实体类:

public class User {
  public String firstName;
  public String lastName;
  public int age;
}

那么对应的 json 串内容如下:

{
   "firstName":"fei",
   "lastName":"liangfei",
   "age":28
}

如果 User 类被混淆掉(成员变量的可能因为没有被用到而被删除或者名字改掉),那序列化工具就无能为力了,因为找不到 json key 与成员变量的对应关系(例如 User.firstName => “firstName”)。

一般的做法会在 proguard 文件中 keep 住 User 的成员变量:

 -keepclassmembernames User.**

但是当多团队合作,代码分散在不同 project 时,每次添加一个实体类还需要修改 proguard 文件,如果多个人同时修改,很可能产生冲突,所以我们必须要想一个一劳永逸的办法。

方法肯定有很多个,Fresco 利用 Annotation - @DoNotSkip 的做法还是比较巧妙的。

首先定义 @DoNotSkip(注释里详细说明了功能):

/**
 * Add this annotation to a class, method, or field to instruct Proguard to not strip it out.
 *
 * This is useful for methods called via reflection that could appear as unused to Proguard.
 */
@Target({ ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR })
@Retention(CLASS)
public @interface DoNotStrip {
}

然后在 proguard 文件中添加如下规则:

# Keep our interfaces so they can be used by other ProGuard rules.
# See http://sourceforge.net/p/proguard/bugs/466/
-keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip

# Do not strip any method/class that is annotated with @DoNotStrip
-keep @com.facebook.common.internal.DoNotStrip class *
-keepclassmembers class * {
    @com.facebook.common.internal.DoNotStrip *;
}

这样一来,我们只要给 User 加上 @DoNotSkip 就不会被混淆掉了。

@DoNotSkip
public class User { }

@DoNotSkip 的定义可以知道它的 target:

@Target({ ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR })

所以,除了类(TYPE)我们还可以把 @DoNotSkip 用于 成员变量(FIELD)、方法(METHOD) 和构造方法(CONSTCTUCTOR)。

@Keep

其实,我们可以不用定义这个 annotation,因为 android support-annotations 包提供了一个与 @DoNotSkip 类似的 annotation - @Keep, 但是现阶段我们仍然需要在 proguard 中一次性添加规则,将来可能就就不需要了。

We’ve also added @Keep to the support annotations. Note however that that annotation hasn’t been hooked up to the Gradle plugin yet (though it’s in progress.) When finished this will let you annotate methods and classes that should be retained when minimizing the app.

以上是关于Fresco 源码解析 - 利用 @DoNotSkip 来防止混淆的主要内容,如果未能解决你的问题,请参考以下文章

Fresco源码赏析 之 基本流程

Fresco源码分析之DraweeView

Fresco源码赏析 之 图片显示流程

Fresco图片框架内部实现原理探索

Fresco图片框架内部实现原理探索

(02)Cartographer源码无死角解析-(23) 传感器数据类型自动推断与数据利用率计算