diff --git a/common/src/main/java/com/numeron/common/State.java b/common/src/main/java/com/numeron/common/State.java index bd24154..cadfa88 100644 --- a/common/src/main/java/com/numeron/common/State.java +++ b/common/src/main/java/com/numeron/common/State.java @@ -2,6 +2,6 @@ public enum State { - Non, Empty, Loading, Failure, Success + Empty, Loading, Failure, Success } diff --git a/stateful-livedata/src/main/java/com/numeron/stateful/livedata/Stateful.kt b/stateful-livedata/src/main/java/com/numeron/stateful/livedata/Stateful.kt new file mode 100644 index 0000000..655e24c --- /dev/null +++ b/stateful-livedata/src/main/java/com/numeron/stateful/livedata/Stateful.kt @@ -0,0 +1,17 @@ +package com.numeron.stateful.livedata + +import com.numeron.common.State + +interface Stateful { + + val state: State + + fun onSuccess(c: (T) -> Unit): Stateful + + fun onFailure(c: (String, Throwable) -> Unit): Stateful + + fun onLoading(c: (String, Float) -> Unit): Stateful + + fun onMessage(c: (String) -> Unit): Stateful + +} \ No newline at end of file diff --git a/stateful-livedata/src/main/java/com/numeron/stateful/livedata/StatefulCallback.kt b/stateful-livedata/src/main/java/com/numeron/stateful/livedata/StatefulCallback.kt new file mode 100644 index 0000000..6848b99 --- /dev/null +++ b/stateful-livedata/src/main/java/com/numeron/stateful/livedata/StatefulCallback.kt @@ -0,0 +1,10 @@ +package com.numeron.stateful.livedata + +interface StatefulCallback { + + fun onSuccess(value: T) + fun onLoading(message: String, progress: Float) + fun onFailure(message: String, cause: Throwable) + fun onMessage(message: String): Unit = Unit + +} \ No newline at end of file diff --git a/stateful-livedata/src/main/java/com/numeron/stateful/livedata/StatefulException.kt b/stateful-livedata/src/main/java/com/numeron/stateful/livedata/StatefulException.kt new file mode 100644 index 0000000..8a7c4cf --- /dev/null +++ b/stateful-livedata/src/main/java/com/numeron/stateful/livedata/StatefulException.kt @@ -0,0 +1,3 @@ +package com.numeron.stateful.livedata + +class StatefulException(override val message: String, cause: Throwable? = null) : RuntimeException(message, cause) \ No newline at end of file diff --git a/stateful-livedata/src/main/java/com/numeron/stateful/livedata/StatefulExceptionHandler.kt b/stateful-livedata/src/main/java/com/numeron/stateful/livedata/StatefulExceptionHandler.kt new file mode 100644 index 0000000..c52ffdc --- /dev/null +++ b/stateful-livedata/src/main/java/com/numeron/stateful/livedata/StatefulExceptionHandler.kt @@ -0,0 +1,35 @@ +package com.numeron.stateful.livedata + +import kotlinx.coroutines.CoroutineExceptionHandler +import java.net.ConnectException +import java.net.SocketTimeoutException +import java.net.UnknownHostException +import kotlin.coroutines.CoroutineContext + +class StatefulExceptionHandler(private val statefulLiveData: StatefulLiveData) : CoroutineExceptionHandler { + + override val key: CoroutineContext.Key<*> + get() = CoroutineExceptionHandler + + override fun handleException(context: CoroutineContext, exception: Throwable) { + exception.printStackTrace() + when (exception) { + is StatefulException -> { + statefulLiveData.postFailure(exception, exception.message) + } + is ConnectException, is UnknownHostException -> { + statefulLiveData.postFailure(exception, "无法连接到服务器,请检查网络后重试。") + } + is SocketTimeoutException -> { + statefulLiveData.postFailure(exception, "网络连接超时,请检查网络后重试。") + } + is NullPointerException -> { + statefulLiveData.postFailure(exception, "没有获取到数据,请稍候重试!") + } + else -> { + statefulLiveData.postFailure(exception) + } + } + } + +} \ No newline at end of file diff --git a/stateful-livedata/src/main/java/com/numeron/stateful/livedata/StatefulImpl.kt b/stateful-livedata/src/main/java/com/numeron/stateful/livedata/StatefulImpl.kt new file mode 100644 index 0000000..045ba44 --- /dev/null +++ b/stateful-livedata/src/main/java/com/numeron/stateful/livedata/StatefulImpl.kt @@ -0,0 +1,43 @@ +package com.numeron.stateful.livedata + +import com.numeron.common.State + +internal data class StatefulImpl( + override val state: State, + internal val success: T? = null, + internal val failure: Throwable? = null, + internal val progress: Float = -1f, + internal val message: String? = null, + internal val version: Int = 0, + internal val previous: Int = 0 +) : Stateful { + + override fun onSuccess(c: (T) -> Unit): Stateful { + if (state == State.Success && success != null) { + c(success) + } + return this + } + + override fun onFailure(c: (String, Throwable) -> Unit): Stateful { + if (state == State.Failure && failure != null) { + c(message!!, failure) + } + return this + } + + override fun onLoading(c: (String, Float) -> Unit): Stateful { + if (state == State.Loading) { + c(message!!, progress) + } + return this + } + + override fun onMessage(c: (String) -> Unit): Stateful { + if (version > previous && message != null) { + c(message) + } + return this + } + +} diff --git a/stateful-livedata/src/main/java/com/numeron/status/StatefulLiveData.kt b/stateful-livedata/src/main/java/com/numeron/stateful/livedata/StatefulLiveData.kt similarity index 61% rename from stateful-livedata/src/main/java/com/numeron/status/StatefulLiveData.kt rename to stateful-livedata/src/main/java/com/numeron/stateful/livedata/StatefulLiveData.kt index 6786ef0..40d61ab 100644 --- a/stateful-livedata/src/main/java/com/numeron/status/StatefulLiveData.kt +++ b/stateful-livedata/src/main/java/com/numeron/stateful/livedata/StatefulLiveData.kt @@ -1,21 +1,19 @@ -package com.numeron.status +package com.numeron.stateful.livedata import androidx.lifecycle.LiveData import com.numeron.common.State class StatefulLiveData @JvmOverloads constructor( - private val empty: String = "没有数据", private val loading: String = "正在加载", - private val success: String = "加载成功", private val failure: String = "加载失败" ) : LiveData>() { private val impl: StatefulImpl - get() = super.getValue() as? StatefulImpl ?: StatefulImpl(State.Non) + get() = getValue() as? StatefulImpl ?: StatefulImpl(State.Empty) val value: T? @JvmName("value") - get() = (super.getValue() as? StatefulImpl)?.success + get() = (getValue() as? StatefulImpl)?.success val requireValue: T @JvmName("requireValue") @@ -30,13 +28,8 @@ class StatefulLiveData @JvmOverloads constructor( postValue(impl.copy(state = State.Loading, progress = progress, message = message)) } - fun postSuccess(value: T, message: String? = this.success) { - postValue(impl.copy(state = State.Success, success = value, message = message)) - } - - @JvmOverloads - fun postEmpty(empty: String = this.empty) { - postValue(impl.copy(state = State.Empty, message = empty)) + fun postSuccess(value: T) { + postValue(impl.copy(state = State.Success, success = value)) } fun postFailure(cause: Throwable, message: String = this.failure) { @@ -48,7 +41,18 @@ class StatefulLiveData @JvmOverloads constructor( } fun postMessage(message: String) { - postValue(impl.copy(state = State.Non, message = message)) + postValue(impl.copy(message = message, previous = impl.version, version = impl.version + 1)) + } + + companion object { + + fun LiveData.toStateful(loading: String = "正在加载", + failure: String = "加载失败"): StatefulLiveData { + val statefulLiveData = StatefulLiveData(loading, failure) + observeForever(statefulLiveData::postSuccess) + return statefulLiveData + } + } } \ No newline at end of file diff --git a/stateful-livedata/src/main/java/com/numeron/status/StatefulObserver.kt b/stateful-livedata/src/main/java/com/numeron/stateful/livedata/StatefulObserver.kt similarity index 73% rename from stateful-livedata/src/main/java/com/numeron/status/StatefulObserver.kt rename to stateful-livedata/src/main/java/com/numeron/stateful/livedata/StatefulObserver.kt index b53f856..157771a 100644 --- a/stateful-livedata/src/main/java/com/numeron/status/StatefulObserver.kt +++ b/stateful-livedata/src/main/java/com/numeron/stateful/livedata/StatefulObserver.kt @@ -1,12 +1,11 @@ -package com.numeron.status +package com.numeron.stateful.livedata import androidx.lifecycle.Observer class StatefulObserver(private val callback: StatefulCallback) : Observer> { override fun onChanged(stateful: Stateful?) { - stateful?.onEmpty(callback::onEmpty) - ?.onFailure(callback::onFailure) + stateful?.onFailure(callback::onFailure) ?.onMessage(callback::onMessage) ?.onLoading(callback::onLoading) ?.onSuccess(callback::onSuccess) diff --git a/stateful-livedata/src/main/java/com/numeron/status/Stateful.kt b/stateful-livedata/src/main/java/com/numeron/status/Stateful.kt deleted file mode 100644 index 940abc9..0000000 --- a/stateful-livedata/src/main/java/com/numeron/status/Stateful.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.numeron.status - -import com.numeron.common.State - -interface Stateful { - - val state: State - - fun onSuccess(c: (T, String?) -> Unit): Stateful - - fun onFailure(c: (Throwable, String?) -> Unit): Stateful - - fun onLoading(c: (Float, String?) -> Unit): Stateful - - fun onMessage(c: (String) -> Unit): Stateful - - fun onEmpty(c: (String) -> Unit): Stateful - -} \ No newline at end of file diff --git a/stateful-livedata/src/main/java/com/numeron/status/StatefulCallback.kt b/stateful-livedata/src/main/java/com/numeron/status/StatefulCallback.kt deleted file mode 100644 index 923a21c..0000000 --- a/stateful-livedata/src/main/java/com/numeron/status/StatefulCallback.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.numeron.status - - -interface StatefulCallback { - - fun onSuccess(value: T, message: String?) - fun onLoading(progress: Float, message: String?) - fun onFailure(cause: Throwable, message: String?) - fun onMessage(message: String) - fun onEmpty(message: String) - -} \ No newline at end of file diff --git a/stateful-livedata/src/main/java/com/numeron/status/StatefulExceptionHandler.kt b/stateful-livedata/src/main/java/com/numeron/status/StatefulExceptionHandler.kt deleted file mode 100644 index 007ab46..0000000 --- a/stateful-livedata/src/main/java/com/numeron/status/StatefulExceptionHandler.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.numeron.status - -import kotlinx.coroutines.CoroutineExceptionHandler -import kotlin.coroutines.CoroutineContext - -class StatefulExceptionHandler(private val statefulLiveData: StatefulLiveData) : CoroutineExceptionHandler { - - override val key: CoroutineContext.Key<*> - get() = CoroutineExceptionHandler - - override fun handleException(context: CoroutineContext, exception: Throwable) { - exception.printStackTrace() - statefulLiveData.postFailure(exception) - } - -} \ No newline at end of file diff --git a/stateful-livedata/src/main/java/com/numeron/status/StatefulImpl.kt b/stateful-livedata/src/main/java/com/numeron/status/StatefulImpl.kt deleted file mode 100644 index cd4f796..0000000 --- a/stateful-livedata/src/main/java/com/numeron/status/StatefulImpl.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.numeron.status - -import com.numeron.common.State - -internal data class StatefulImpl( - override val state: State, - internal val success: T? = null, - internal val failure: Throwable? = null, - internal val progress: Float = -1f, - internal val message: String? = null -) : Stateful { - - override fun onSuccess(c: (T, String?) -> Unit): Stateful { - if (state == State.Success && success != null) { - c(success, message) - } - return this - } - - override fun onFailure(c: (Throwable, String?) -> Unit): Stateful { - if (state == State.Failure && failure != null) { - c(failure, message) - } - return this - } - - override fun onLoading(c: (Float, String?) -> Unit): Stateful { - if (state == State.Loading && progress > 0f) { - c(progress, message) - } - return this - } - - override fun onEmpty(c: (String) -> Unit): Stateful { - if (state == State.Empty && message != null) { - c(message) - } - return this - } - - override fun onMessage(c: (String) -> Unit): Stateful { - if (state == State.Non && message != null) { - c(message) - } - return this - } - -}