-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
= optimize the issue caused by R8(Proguard tools)
- Loading branch information
Showing
6 changed files
with
146 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,6 +39,7 @@ captures/ | |
|
||
# Intellij | ||
.idea/ | ||
.bsp/ | ||
|
||
# Keystore files | ||
*.jks |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
version = 2.7.3 | ||
|
||
preset = IntelliJ | ||
align.preset = more # For pretty alignment. | ||
maxColumn = 230 # For my wide 30" display. | ||
|
||
# 注释不能使用';'号,虽然按 'command + /' 会出现分号。 | ||
assumeStandardLibraryStripMargin = true | ||
align.stripMargin = true | ||
|
||
continuationIndent.callSite = 2 | ||
continuationIndent.ctorSite = 4 | ||
continuationIndent.defnSite = 2 | ||
continuationIndent.extendSite = 4 | ||
continuationIndent.withSiteRelativeToExtends = 3 | ||
|
||
indentOperator.topLevelOnly = false | ||
# indentOperator.exclude = "^(&&|\\|\\|)$" | ||
# indentOperator.include = ".*" | ||
indentOperator.preset = spray # default | spray (set include = "^.*=$", exclude = "^$") | ||
|
||
align.preset = more # none | some | more | most | ||
align.arrowEnumeratorGenerator = true | ||
# align.openParenDefnSite = false | ||
|
||
newlines.source = keep # classic | keep | fold | unfold | ||
newlines.beforeMultiline = keep # classic | keep | fold | unfold | ||
newlines.beforeMultilineDef = keep | ||
newlines.topLevelStatements = [before] # [before, after] | ||
# newlines.topLevelStatementsMinBreaks = 1 # 至少跨越多少行,才可以自动换行。 | ||
|
||
# optIn.configStyleArguments = true | ||
# 方法调用的括号内,可见参数字符数量(包括逗号)。如果字符数 >= 这个数,则触发折行。 | ||
# runner.optimizer.forceConfigStyleOnOffset = 150 | ||
# runner.optimizer.forceConfigStyleMinArgCount = 1 # 最少参数数量 | ||
# optIn.breaksInsideChains = false | ||
optIn.encloseClassicChains = true | ||
optIn.forceBlankLineBeforeDocstring = false | ||
|
||
rewrite.rules = [SortModifiers] | ||
rewrite.rules = [SortImports] | ||
|
||
trailingCommas = preserve # never | preserve | always | multiple | ||
|
||
# verticalMultiline.atDefnSite = true | ||
# verticalMultiline.arityThreshold = 100 | ||
# verticalMultiline.newlineAfterOpenParen = false | ||
|
||
binPack.parentConstructors = OnelineIfPrimaryOneline | ||
|
||
# // format: off | ||
# val identity = Array(1, 0, 0, | ||
# 0, 1, 0, | ||
# 0, 0, 1) | ||
# // format: on |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
sbt.version=0.13.18 | ||
sbt.version=1.9.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,10 +25,11 @@ | |
import java.util.Locale; | ||
|
||
/** | ||
* 摘自Gson源码。 | ||
* 摘自`Gson`源码。 | ||
* | ||
* @author Wei Chou([email protected]) | ||
* @version 1.0, 02/07/2016 | ||
* @version 1.0, 02/07/2016; | ||
* 1.1, 同步至 {@code Gson 2.10.1} | ||
*/ | ||
public class Reflect { | ||
public static Type[] getSuperclassTypeParameter(Class<?> subclass, boolean checkTypeVariable) { | ||
|
@@ -38,35 +39,62 @@ public static Type[] getSuperclassTypeParameter(Class<?> subclass, boolean check | |
} else { | ||
final Type[] types = ((ParameterizedType) superclass).getActualTypeArguments(); | ||
if (checkTypeVariable) { | ||
for (Type t : types) { | ||
if (t instanceof TypeVariable) { | ||
throwClassIllegal(subclass); | ||
} | ||
for (Type tpe : types) { | ||
checkTypeVariable(tpe); | ||
} | ||
} | ||
return types; | ||
} | ||
} | ||
|
||
public static Class<?> getRawType(Type type) { | ||
if (type instanceof Class) { | ||
return (Class) type; | ||
} else if (type instanceof ParameterizedType) { | ||
return (Class) ((ParameterizedType) type).getRawType(); | ||
} else if (type instanceof GenericArrayType) { | ||
return Array.newInstance(getRawType(((GenericArrayType) type).getGenericComponentType()), 0).getClass(); | ||
} else if (type instanceof TypeVariable) { | ||
/** | ||
* 借鉴 {@code Gson 2.10.1}, 实测与上面效果一样(问题不在 scala/java, 而在 Android, 与 R8 有关,已找到原因)。 | ||
*/ | ||
public static Type[] getSuperclassTypeParameterSafe(Class<?> subclass, boolean checkTypeVariable) { | ||
final Type superclass = subclass.getGenericSuperclass(); | ||
if (superclass instanceof ParameterizedType) { | ||
final Type[] types = ((ParameterizedType) superclass).getActualTypeArguments(); | ||
if (checkTypeVariable) { | ||
for (Type tpe : types) { | ||
checkTypeVariable(tpe); | ||
} | ||
} | ||
return types; | ||
} | ||
return throwClassIllegal(subclass); | ||
} | ||
|
||
public static void checkTypeVariable(Type tpe) { | ||
// `TypeVariable`表示`T`占位符而不是具体类型,如`Xx<T>`而不是`Xx<java.util.ArrayList<?>>`。 | ||
// 区别于`WildcardType`。 | ||
if (tpe instanceof TypeVariable) { | ||
// ((TypeVariable<?>)tpe).getBounds(); // 表示获取`T`参数表示的具体类,如: | ||
// `java.util.ArrayList<?>`,这需要递归,具体看在第几层。 | ||
throwTypeIllegal(tpe); | ||
} | ||
} | ||
|
||
public static Class<?> getRawType(Type tpe) { | ||
if (tpe instanceof Class) { | ||
return (Class<?>) tpe; | ||
} else if (tpe instanceof ParameterizedType) { | ||
return (Class<?>) ((ParameterizedType) tpe).getRawType(); | ||
} else if (tpe instanceof GenericArrayType) { | ||
return Array.newInstance(getRawType(((GenericArrayType) tpe).getGenericComponentType()), 0).getClass(); | ||
} else if (tpe instanceof TypeVariable) { | ||
// we could use the variable's bounds, but that won't work if there are multiple. | ||
// having a raw type that's more general than necessary is okay | ||
return Object.class; | ||
} else if (type instanceof WildcardType) { | ||
return getRawType(((WildcardType) type).getUpperBounds()[0]); | ||
} else if (tpe instanceof WildcardType) { | ||
return getRawType(((WildcardType) tpe).getUpperBounds()[0]); | ||
} else { | ||
return throwTypeIllegal(type); | ||
return throwTypeIllegal(tpe); | ||
} | ||
} | ||
|
||
public static Type[] getSubTypes(Type type) { | ||
if (type instanceof ParameterizedType) { | ||
return ((ParameterizedType) type).getActualTypeArguments(); | ||
public static Type[] getSubTypes(Type tpe) { | ||
if (tpe instanceof ParameterizedType) { | ||
return ((ParameterizedType) tpe).getActualTypeArguments(); | ||
} else { | ||
return EMPTY_TYPES; | ||
} | ||
|
@@ -77,10 +105,9 @@ private static Type[] throwClassIllegal(Class<?> subclass) { | |
Locale.CHINA, "请确保类\"%s\"是泛型类的[匿名]子类。", subclass.getName())); | ||
} | ||
|
||
private static Class<?> throwTypeIllegal(Type type) { | ||
private static Class<?> throwTypeIllegal(Type tpe) { | ||
throw new IllegalArgumentException(String.format( | ||
// Locale.CHINA, "不支持的类型\"%s\", 仅支持Class, ParameterizedType, or GenericArrayType.", type)); | ||
Locale.CHINA, "不支持的类型\"%s\", 请确认泛型参数是否正确。", type)); | ||
Locale.CHINA, "不支持的类型\"%s\", 请确认泛型参数是否正确。", tpe)); | ||
} | ||
|
||
private static final Type[] EMPTY_TYPES = new Type[0]; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,49 +19,43 @@ package hobby.wei.c.reflow | |
import java.lang.reflect.Type | ||
import hobby.chenai.nakam.lang.J2S.NonNull | ||
import hobby.chenai.nakam.lang.TypeBring.AsIs | ||
import hobby.wei.c.anno.proguard.{Keep$$e, KeepC$$e} | ||
import hobby.wei.c.tool.Reflect | ||
|
||
import scala.collection._ | ||
|
||
/** | ||
* 定义key及value类型。value类型由泛型指定。 | ||
* 注意: 本类的子类必须在运行时创建, 即匿名子类, 否则泛型信息可能在Proguard时被删除, 从而导致解析失败。 | ||
* 定义`key`及`value`类型。`value`类型由泛型指定。 | ||
* 注意: 本类的子类必须在运行时创建, 即匿名子类, 否则泛型信息可能在`Proguard`时被删除, 从而导致解析失败。 | ||
* | ||
* @author Wei Chou([email protected]) | ||
* @version 1.0, 21/07/2016 | ||
*/ | ||
abstract class KvTpe[T <: AnyRef] private[reflow](_key: String, _clazz: Class[_], _index: Int = 0, _raw: Boolean = false) extends Equals { | ||
@Keep$$e @KeepC$$e | ||
abstract class KvTpe[T <: AnyRef] private[reflow] (_key: String, _clazz: Class[_], _index: Int = 0, _raw: Boolean = false) extends Equals { | ||
protected def this(_key: String) = this(_key, null) | ||
|
||
final val key: String = _key.ensuring(_.nonEmpty) | ||
/** | ||
* 泛型参数的类型, 类似于这种结构: java.util.List<java.util.List<int[]>>。 | ||
*/ | ||
final val tpe: Type = (if (_raw) _clazz else Reflect.getSuperclassTypeParameter(if (_clazz.isNull) this.getClass else _clazz, true)(_index)).ensuring(_.nonNull) | ||
/** | ||
* 第一级泛型参数的Class表示。 | ||
*/ | ||
|
||
/** 泛型参数的类型, 类似于这种结构: `java.util.List<java.util.List<int[]>>`。 */ | ||
final val tpe: Type = (if (_raw) _clazz else Reflect.getSuperclassTypeParameterSafe(if (_clazz.isNull) this.getClass else _clazz, true)(_index)).ensuring(_.nonNull) | ||
|
||
/** 第一级泛型参数的`Class`表示。 */ | ||
private lazy val rawType: Class[_ >: T] = Reflect.getRawType(tpe).as[Class[_ >: T]] | ||
/** | ||
* 第一级泛型参数的子泛型参数, 可能不存在。作用或结构与tpe类似。 | ||
*/ | ||
|
||
/** 第一级泛型参数的子泛型参数, 可能不存在。作用或结构与`tpe`类似。 */ | ||
private lazy val subTypes: Array[Type] = Reflect.getSubTypes(tpe) | ||
|
||
/** | ||
* 走这个方法作类型转换, 确保value类型与定义的一致性。 | ||
* @return 返回Task在执行时当前key对应值的目标类型。 | ||
*/ | ||
/** 走这个方法作类型转换, 确保`value`类型与定义的一致性。 */ | ||
def asType(value: Any): T = value.as[T] | ||
|
||
def putValue(map: mutable.Map[String, Any], value: Any): Boolean = putValue(map, value, ignoreTpeDiff = false) | ||
|
||
/** | ||
* 将输出值按指定类型(作类型检查)插入Map。 | ||
* | ||
* @param map 输出到的Map。 | ||
* @param value 要输出的值。 | ||
* @param ignoreTpeDiff 如果value参数类型不匹配,是否忽略。 | ||
* @return true成功,else失败。 | ||
/** 将输出值按指定类型(作类型检查)插入`Map`。 | ||
* @param map 输出到的`Map` | ||
* @param value 要输出的值 | ||
* @param ignoreTpeDiff 如果`value`参数类型不匹配,是否忽略。 | ||
* @return `true`成功,`else`失败。 | ||
*/ | ||
def putValue(map: mutable.Map[String, Any], value: Any, ignoreTpeDiff: Boolean): Boolean = { | ||
val v = requireSameType(value, ignoreTpeDiff) | ||
|
@@ -71,15 +65,13 @@ abstract class KvTpe[T <: AnyRef] private[reflow](_key: String, _clazz: Class[_] | |
} else false | ||
} | ||
|
||
/** | ||
* 走这个方法取值, 确保value类型与定义的一致性。 | ||
* | ||
* @param map Task的输入参数。 | ||
* @return 返回Task在执行时当前key对应值的目标类型。 | ||
/** 走这个方法取值, 确保`value`类型与定义的一致性。 | ||
* @param map `Task`的输入参数 | ||
* @return 返回`Task`在执行时当前`key`对应值的目标类型 | ||
*/ | ||
def takeValue(map: Map[String, Any]): Option[T] = { | ||
// 强制类型转换比较宽松, 只会检查对象类型, 而不会检查泛型。 | ||
// 但是由于value值对象无法获得泛型类型, 因此这里不再作泛型检查。也避免了性能问题。 | ||
// 但是由于`value`值对象无法获得泛型类型, 因此这里不再作泛型检查。也避免了性能问题。 | ||
map.get(key).as[Option[T]] | ||
} | ||
|
||
|
@@ -90,17 +82,11 @@ abstract class KvTpe[T <: AnyRef] private[reflow](_key: String, _clazz: Class[_] | |
if (ignoreDiffType) null | ||
else Assist.Throws.typeNotMatch(this, clazz) | ||
} else value | ||
// 数值对象通常已经失去了泛型参数, 因此不作检查 | ||
// 数值对象通常已经失去了泛型参数, 因此不作检查。 | ||
} else value | ||
} | ||
|
||
/** | ||
* 参数的value类型是否与本value类型相同或者子类型。 | ||
* 同{Class#isAssignableFrom(Class)} | ||
* | ||
* @param key | ||
* @return | ||
*/ | ||
/** 参数的`value`类型是否与本`value`类型相同或者子类型。同`Class#isAssignableFrom(Class)`。 */ | ||
def isAssignableFrom(key: KvTpe[_ <: AnyRef]): Boolean = { | ||
if (!rawType.isAssignableFrom(key.rawType)) false | ||
else if (subTypes.length != key.subTypes.length) false | ||
|
@@ -109,7 +95,7 @@ abstract class KvTpe[T <: AnyRef] private[reflow](_key: String, _clazz: Class[_] | |
|
||
override def equals(any: scala.Any) = any match { | ||
case that: KvTpe[_] if that.canEqual(this) => that.key == this.key && that.tpe == this.tpe | ||
case _ => false | ||
case _ => false | ||
} | ||
|
||
override def canEqual(that: Any) = that.isInstanceOf[KvTpe[_]] | ||
|