add FragmentArgumentDelegate

androidx
Ztiany 5 years ago
parent 601ea902c3
commit 6448dfbf2c
  1. 57
      lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectableExtension.kt
  2. 114
      lib_base/src/main/java/com/android/base/app/fragment/tools/FragmentArgumentDelegate.kt

@ -1,7 +1,13 @@
package com.android.base.app.fragment.injectable
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.android.base.app.ui.LoadingView
import com.android.base.data.ErrorHandler
import com.android.base.data.Resource
import timber.log.Timber
interface InjectableExtension {
@ -11,3 +17,54 @@ interface InjectableExtension {
val errorHandler: ErrorHandler
}
fun <H, T> H.handleLiveResource(
liveData: LiveData<Resource<T>>,
force: Boolean = true,
onSuccess: (T?) -> Unit
) where H : InjectableExtension, H : LoadingView, H : LifecycleOwner {
liveData.observe(this, Observer {
when {
it.isError -> {
Timber.d("handleLiveResource -> isError")
dismissLoadingDialog()
errorHandler.handleError(it.error())
}
it.isLoading -> {
Timber.d("handleLiveResource -> isLoading")
showLoadingDialog(!force)
}
it.isSuccess -> {
Timber.d("handleLiveResource -> isSuccess")
dismissLoadingDialog()
onSuccess(it.get())
}
}
})
}
fun <H, T> H.handleLiveResourceWithData(
liveData: LiveData<Resource<T>>,
force: Boolean = true,
onSuccess: (T) -> Unit
) where H : InjectableExtension, H : LoadingView, H : LifecycleOwner {
liveData.observe(this, Observer {
when {
it.isError -> {
dismissLoadingDialog()
errorHandler.handleError(it.error())
}
it.isLoading -> {
showLoadingDialog(!force)
}
it.isSuccess && it.hasData() -> {
dismissLoadingDialog()
onSuccess(it.data())
}
}
})
}

@ -0,0 +1,114 @@
package com.android.base.app.fragment.tools
import android.os.Binder
import android.os.Bundle
import androidx.core.app.BundleCompat
import androidx.fragment.app.Fragment
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
fun <T : Any> fragmentArgument(name: String? = null, defaultValue: T? = null): ReadWriteProperty<Fragment, T> {
return FragmentArgumentDelegate(name, defaultValue)
}
fun <T : Any?> nullableFragmentArgument(name: String? = null): ReadWriteProperty<Fragment, T?> {
return NullableFragmentArgumentDelegate(name)
}
internal class FragmentArgumentDelegate<T : Any>(
/**value name*/
private val name: String? = null,
/**default cannot be null*/
private val defaultValue: T? = null
) : ReadWriteProperty<Fragment, T> {
private lateinit var value: T
override operator fun getValue(thisRef: Fragment, property: KProperty<*>): T {
if (!::value.isInitialized) {
val args = thisRef.arguments
if (args == null) {
if (defaultValue != null) {
value = defaultValue
} else {
throw IllegalStateException("Cannot read property ${confirmPropertyName(name, property)} if no arguments have been set")
}
} else {
@Suppress("UNCHECKED_CAST")
value = args.get(confirmPropertyName(name, property)) as? T
?: throw IllegalStateException("Property ${confirmPropertyName(name, property)} could not be read")
}
}
return value
}
override operator fun setValue(thisRef: Fragment, property: KProperty<*>, value: T) {
this.value = value
saveValue(thisRef, name, property, value)
}
}
internal class NullableFragmentArgumentDelegate<T : Any?>(
/**value name*/
private val name: String? = null
) : ReadWriteProperty<Fragment, T?> {
private var value: T? = null
override operator fun getValue(thisRef: Fragment, property: KProperty<*>): T? {
if (value == null) {
@Suppress("UNCHECKED_CAST")
value = thisRef.arguments?.get(confirmPropertyName(name, property)) as? T
}
return value
}
override operator fun setValue(thisRef: Fragment, property: KProperty<*>, value: T?) {
this.value = value
saveValue(thisRef, name, property, value)
}
}
private fun confirmPropertyName(name: String?, property: KProperty<*>): String {
return name ?: property.name
}
private fun saveValue(thisRef: Fragment, name: String?, property: KProperty<*>, value: Any?) {
var args = thisRef.arguments
val key = confirmPropertyName(name, property)
if (value == null) {
args?.remove(key)
return
}
if (args == null) {
args = Bundle()
thisRef.arguments = args
}
when (value) {
is String -> args.putString(key, value)
is Int -> args.putInt(key, value)
is Short -> args.putShort(key, value)
is Long -> args.putLong(key, value)
is Byte -> args.putByte(key, value)
is ByteArray -> args.putByteArray(key, value)
is Char -> args.putChar(key, value)
is CharArray -> args.putCharArray(key, value)
is CharSequence -> args.putCharSequence(key, value)
is Float -> args.putFloat(key, value)
is Bundle -> args.putBundle(key, value)
is Binder -> BundleCompat.putBinder(args, key, value)
is android.os.Parcelable -> args.putParcelable(key, value)
is java.io.Serializable -> args.putSerializable(key, value)
else -> throw IllegalStateException("Type \"$value\" of property ${property.name} is not supported")
}
}
Loading…
Cancel
Save