前言
寫項(xiàng)目的時(shí)候經(jīng)常會(huì)寫到跳轉(zhuǎn)Activiey,寫到跳轉(zhuǎn)Activit就一定會(huì)寫到putExtra,就像下面那樣
intent.putExtra("a", item.a)
intent.putExtra("b", item.b)
intent.putExtra("c", item.c)
挺多哈,每次都要重復(fù)前面相同的內(nèi)容,所以就想著能不能寫個(gè)擴(kuò)展來簡寫。
開始
我們最終實(shí)現(xiàn)是這樣的:
Intent(context, TestActivity::class.java)
.putExtraVararg(
"a" to item.a,
"b" to item.b,
"c" to item.c
)
仿mapOf
經(jīng)常用到mapOf()
或者mutableMapOf()
就會(huì)知道,里面是用了Pair
類來生成Map的,所以受此啟發(fā),打算用Pair
來作為參數(shù)實(shí)現(xiàn),那么寫的時(shí)候就應(yīng)該是這樣寫,參數(shù)為可變參數(shù)類型:
// 作為Intent的擴(kuò)展
fun Intent.putExtraVararg(
vararg extras: Pair<String, Any?>
): Intent {
// 先省略
}
putExtra
的第一個(gè)參數(shù)類型肯定是String
類型,第二個(gè)參數(shù)的類型包括Bundle, Boolean, BooleanArray, Byte, ByteArray, Char, CharArray, String
等等,所以就用Any
類型,因?yàn)槭强煽盏模约由?code>?。
那么調(diào)用的時(shí)候,就是這樣子的
Intent(context, TestActivity::class.java)
.putExtraVararg(
"a" to item.a,
"b" to item.b,
"c" to item.c
)
是不是就是一開始說的那樣,對(duì)比平常寫的是不是簡單了很多。
參數(shù)類型匹配
寫好了參數(shù),那么就要進(jìn)行對(duì)參數(shù)類型的匹配進(jìn)行對(duì)應(yīng)的putExtra
。
vararg
參數(shù)可以用forEach
來循環(huán)對(duì)每個(gè)參數(shù)類型進(jìn)行匹配:
fun Intent.putExtraVararg(
vararg extras: Pair<String, Any?>
): Intent {
if (extras.isEmpty()) return this
extras.forEach { (key, value) ->
value ?: let {
it.putExtra(key, it.toString())
return@forEach
}
when (value) {
is Bundle -> this.putExtra(key, value)
is Boolean -> this.putExtra(key, value)
is BooleanArray -> this.putExtra(key, value)
is Byte -> this.putExtra(key, value)
is ByteArray -> this.putExtra(key, value)
is Char -> this.putExtra(key, value)
is CharArray -> this.putExtra(key, value)
is String -> this.putExtra(key, value)
is CharSequence -> this.putExtra(key, value)
is Double -> this.putExtra(key, value)
is DoubleArray -> this.putExtra(key, value)
is Float -> this.putExtra(key, value)
is FloatArray -> this.putExtra(key, value)
is Int -> this.putExtra(key, value)
is IntArray -> this.putExtra(key, value)
is Long -> this.putExtra(key, value)
is LongArray -> this.putExtra(key, value)
is Short -> this.putExtra(key, value)
is ShortArray -> this.putExtra(key, value)
is Parcelable -> this.putExtra(key, value)
is Serializable -> this.putExtra(key, value)
else -> {
throw IllegalArgumentException("Not support $value type ${value.javaClass}..")
}
}
}
return this
}
發(fā)現(xiàn)沒有,還少了ArrayList<String>
、ArrayList<CharSequence>
、ArrayList<? extends Parcelable>
這三個(gè)List的參數(shù)類型匹配,因?yàn)椴荒苤苯?code>is來匹配對(duì)應(yīng)的Array類型,在群里問過之后,才得出最終的方法,Array里面有一個(gè)匹配對(duì)應(yīng)類型的擴(kuò)展函數(shù)isArrayOf()
:
/**
* Checks if array can contain element of type [T].
*/
@Suppress("REIFIED_TYPE_PARAMETER_NO_INLINE")
public fun <reified T : Any> Array<*>.isArrayOf(): Boolean =
T::class.java.isAssignableFrom(this::class.java.componentType)
so,這樣就簡單了,我們先匹配Array
,然后在匹配對(duì)應(yīng)的ArrayList<String>
、ArrayList<CharSequence>
、ArrayList<? extends Parcelable>
,最后在對(duì)應(yīng)put方法那里用as
:
is Array<*> -> {
@Suppress("UNCHECKED_CAST")
when {
value.isArrayOf<String>() -> {
this.putStringArrayListExtra(key, value as ArrayList<String?>)
}
value.isArrayOf<CharSequence>() -> {
this.putCharSequenceArrayListExtra(key, value as ArrayList<CharSequence?>)
}
value.isArrayOf<Parcelable>() -> {
this.putParcelableArrayListExtra(key, value as ArrayList<out Parcelable?>)
}
}
}
這樣就實(shí)現(xiàn)了不同Array
類型的putExtra
。
最終
最后完整的代碼為
fun Intent.putExtraVararg(
vararg extras: Pair<String, Any?>
): Intent {
if (extras.isEmpty()) return this
extras.forEach {
val key = it.first
val value = it.second ?: let {
it.putExtra(key, it.toString())
}
}
extras.forEach { (key, value) ->
value ?: let {
it.putExtra(key, it.toString())
return@forEach
}
when (value) {
is Bundle -> this.putExtra(key, value)
is Boolean -> this.putExtra(key, value)
is BooleanArray -> this.putExtra(key, value)
is Byte -> this.putExtra(key, value)
is ByteArray -> this.putExtra(key, value)
is Char -> this.putExtra(key, value)
is CharArray -> this.putExtra(key, value)
is String -> this.putExtra(key, value)
is CharSequence -> this.putExtra(key, value)
is Double -> this.putExtra(key, value)
is DoubleArray -> this.putExtra(key, value)
is Float -> this.putExtra(key, value)
is FloatArray -> this.putExtra(key, value)
is Int -> this.putExtra(key, value)
is IntArray -> this.putExtra(key, value)
is Long -> this.putExtra(key, value)
is LongArray -> this.putExtra(key, value)
is Short -> this.putExtra(key, value)
is ShortArray -> this.putExtra(key, value)
is Array<*> -> {
@Suppress("UNCHECKED_CAST")
when {
value.isArrayOf<String>() -> {
this.putStringArrayListExtra(key, value as ArrayList<String?>)
}
value.isArrayOf<CharSequence>() -> {
this.putCharSequenceArrayListExtra(key, value as ArrayList<CharSequence?>)
}
value.isArrayOf<Parcelable>() -> {
this.putParcelableArrayListExtra(key, value as ArrayList<out Parcelable?>)
}
}
}
is Parcelable -> this.putExtra(key, value)
is Serializable -> this.putExtra(key, value)
else -> {
throw IllegalArgumentException("Not support $value type ${value.javaClass}..")
}
}
}
return this
}
轉(zhuǎn)成Java是這樣的:
public final class IntentExtKt {
@NotNull
public static final Intent putExtraVararg(@NotNull Intent $receiver, @NotNull Pair... extras) {
Intrinsics.checkParameterIsNotNull($receiver, "receiver$0");
Intrinsics.checkParameterIsNotNull(extras, "extras");
if (extras.length == 0) {
return $receiver;
} else {
Pair[] var3 = extras;
int var4 = extras.length;
int var5;
Pair element$iv;
boolean var8;
String key;
for(var5 = 0; var5 < var4; ++var5) {
element$iv = var3[var5];
var8 = false;
key = (String)element$iv.getFirst();
if (element$iv.getSecond() == null) {
int var12 = false;
$receiver.putExtra(key, $receiver.toString());
}
}
var3 = extras;
var4 = extras.length;
for(var5 = 0; var5 < var4; ++var5) {
element$iv = var3[var5];
var8 = false;
key = (String)element$iv.component1();
Object value = element$iv.component2();
if (value != null) {
if (value instanceof Bundle) {
$receiver.putExtra(key, (Bundle)value);
} else if (value instanceof Boolean) {
$receiver.putExtra(key, (Boolean)value);
} else if (value instanceof boolean[]) {
$receiver.putExtra(key, (boolean[])value);
} else if (value instanceof Byte) {
$receiver.putExtra(key, ((Number)value).byteValue());
} else if (value instanceof byte[]) {
$receiver.putExtra(key, (byte[])value);
} else if (value instanceof Character) {
$receiver.putExtra(key, (Character)value);
} else if (value instanceof char[]) {
$receiver.putExtra(key, (char[])value);
} else if (value instanceof String) {
$receiver.putExtra(key, (String)value);
} else if (value instanceof CharSequence) {
$receiver.putExtra(key, (CharSequence)value);
} else if (value instanceof Double) {
$receiver.putExtra(key, ((Number)value).doubleValue());
} else if (value instanceof double[]) {
$receiver.putExtra(key, (double[])value);
} else if (value instanceof Float) {
$receiver.putExtra(key, ((Number)value).floatValue());
} else if (value instanceof float[]) {
$receiver.putExtra(key, (float[])value);
} else if (value instanceof Integer) {
$receiver.putExtra(key, ((Number)value).intValue());
} else if (value instanceof int[]) {
$receiver.putExtra(key, (int[])value);
} else if (value instanceof Long) {
$receiver.putExtra(key, ((Number)value).longValue());
} else if (value instanceof long[]) {
$receiver.putExtra(key, (long[])value);
} else if (value instanceof Short) {
$receiver.putExtra(key, ((Number)value).shortValue());
} else if (value instanceof short[]) {
$receiver.putExtra(key, (short[])value);
} else if (value instanceof Object[]) {
if ((Object[])value instanceof String[]) {
$receiver.putStringArrayListExtra(key, (ArrayList)value);
} else if ((Object[])value instanceof CharSequence[]) {
$receiver.putCharSequenceArrayListExtra(key, (ArrayList)value);
} else if ((Object[])value instanceof Parcelable[]) {
$receiver.putParcelableArrayListExtra(key, (ArrayList)value);
}
} else if (value instanceof Parcelable) {
$receiver.putExtra(key, (Parcelable)value);
} else {
if (!(value instanceof Serializable)) {
throw (Throwable)(new IllegalArgumentException("Not support " + value + " type " + value.getClass() + ".."));
}
$receiver.putExtra(key, (Serializable)value);
}
} else {
int var13 = false;
$receiver.putExtra(key, $receiver.toString());
}
}
return $receiver;
}
}
}
順手寫別的擴(kuò)展
既然用到Intent的擴(kuò)展,那么就順手寫下Activity的startActivity的擴(kuò)展
/**
* 同Context的startActivity
*/
fun Context.toActivity(packageContext: Context?, cls: Class<*>, vararg extras: Pair<String, Any?>) {
startActivity(Intent(packageContext, cls).putExtraVararg(*extras))
}
/**
* 同Context的startActivity
*/
fun Context.toActivity(intent: Intent) {
startActivity(intent)
}
調(diào)用的時(shí)候就是這樣子的
context.toActivity(
context,
SearchActivity::class.java,
SearchActivity.SEARCH_TYPE to item.type,
SearchActivity.SEARCH_UID to item.uid,
SearchActivity.SEARCH_NAME to item.name,
SearchActivity.SEARCH_KEY to item.key,
SearchActivity.SEARCH_GROUP to item.group
)
總結(jié)
通過這次的擴(kuò)展,也學(xué)到了關(guān)于Array
的一些擴(kuò)展函數(shù),可以說是很美好了。