diff --git a/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectableExtension.kt b/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectableExtension.kt index d1cbbc9..ac687cf 100644 --- a/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectableExtension.kt +++ b/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectableExtension.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.handleLiveResource( + liveData: LiveData>, + 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.handleLiveResourceWithData( + liveData: LiveData>, + 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()) + } + } + }) + +} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/fragment/tools/FragmentArgumentDelegate.kt b/lib_base/src/main/java/com/android/base/app/fragment/tools/FragmentArgumentDelegate.kt new file mode 100644 index 0000000..43562b0 --- /dev/null +++ b/lib_base/src/main/java/com/android/base/app/fragment/tools/FragmentArgumentDelegate.kt @@ -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 fragmentArgument(name: String? = null, defaultValue: T? = null): ReadWriteProperty { + return FragmentArgumentDelegate(name, defaultValue) +} + +fun nullableFragmentArgument(name: String? = null): ReadWriteProperty { + return NullableFragmentArgumentDelegate(name) +} + +internal class FragmentArgumentDelegate( + /**value name*/ + private val name: String? = null, + /**default cannot be null*/ + private val defaultValue: T? = null +) : ReadWriteProperty { + + 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( + /**value name*/ + private val name: String? = null +) : ReadWriteProperty { + + 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") + } +} \ No newline at end of file