Kotlin Result类
Kotlin Result类
自定义 Result 类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
internal suspend inline fun <reified T> BaseRxHttp.awaitResult(timeoutMillis: Long = 0L): Result<T> {
return runCatching {
if (timeoutMillis <= 0L) {
asClassSuspend<T>().await()
} else {
withTimeout(timeoutMillis) {
asClassSuspend<T>().await()
}
}
}
}
@OptIn(ExperimentalContracts::class)
@SinceKotlin("1.3")
internal inline fun <T> Result<T>.onFailure(
crossinline action: (exception: Throwable, isTimeout: Boolean) -> Unit
): Result<T> {
contract {
callsInPlace(action, InvocationKind.AT_MOST_ONCE)
}
exceptionOrNull()?.let {
if (it is kotlinx.coroutines.TimeoutCancellationException) {
action(it, true)
} else {
action(it, false)
}
}
return this
}
// region AppWidget 专用
@OptIn(ExperimentalContracts::class)
inline fun <T> Result<AppWidgetData<T>>.onAppWidgetSuccess(action: (value: AppWidgetData<T>) -> Unit): Result<AppWidgetData<T>> {
contract {
callsInPlace(action, InvocationKind.AT_MOST_ONCE)
}
if (isSuccess) {
val data = getOrNull()
if (data != null && data.isValid()) {
WidgetMonitor.requestDataStatus(data.appWidgetLayoutCode, false)
action(data)
}
}
return this
}
@OptIn(ExperimentalContracts::class)
internal inline fun <T> Result<AppWidgetData<T>>.onAppWidgetFailure(
crossinline action: (e: Throwable, value: AppWidgetData<T>) -> Unit
): Result<AppWidgetData<T>> {
contract {
callsInPlace(action, InvocationKind.AT_MOST_ONCE)
}
if (isSuccess) {
val data = getOrNull()
if (data != null && !data.isValid()) {
WidgetMonitor.requestDataStatus(data.appWidgetLayoutCode, true)
action(data.tr ?: Throwable("data is invalid"), data)
}
}
return this
}
internal suspend inline fun <reified T> BaseRxHttp.awaitAppWidgetResult(
@AppWidgetLayoutCode
appWidgetLayoutCode: String,
callType: String? = "",
): Result<AppWidgetData<T>> {
val s = SystemClock.elapsedRealtime()
return try {
callType?.let {
WidgetMonitor.requestData(appWidgetLayoutCode, it)
}
val data = asClassSuspend<T>().await()
val cost = SystemClock.elapsedRealtime() - s
WidgetMonitor.requestDataCost(appWidgetLayoutCode, callType, cost)
Result.success(
AppWidgetData(
appWidgetLayoutCode = appWidgetLayoutCode,
callType = callType,
data = data,
cost = cost
)
)
} catch (e: Throwable) {
val cost = SystemClock.elapsedRealtime() - s
WidgetMonitor.requestDataCost(appWidgetLayoutCode, callType, cost)
Result.success(
AppWidgetData(
appWidgetLayoutCode = appWidgetLayoutCode,
callType = callType,
data = null,
cost = cost,
tr = e
)
)
}
}
data class AppWidgetData<T>(
@AppWidgetLayoutCode
val appWidgetLayoutCode: String,
val callType: String? = "",
val data: T? = null,
val cost: Long = 0L,
val tr: Throwable? = null
) {
fun isValid(): Boolean {
return data != null
}
fun isSuccess(): Boolean {
return tr == null && data != null
}
}
// endregion
awaitAppWidgetResult和jacoco插件编译不过问题
- 大意就是 google 工程师说是 jacoco 插桩问题导致字节码 invalid 了
- com.android.tools.r8.CompilationFailedException 384636715 - Issue Tracker
- 解决方案是 jacoco 屏蔽掉该类
Result 扩展
本文由作者按照 CC BY 4.0 进行授权