split basefragment and state saving

This commit is contained in:
Максим Бачинский 2020-05-27 20:41:46 +03:00
parent 8399f01d50
commit 45dddff10a
4 changed files with 60 additions and 41 deletions

View File

@ -29,7 +29,7 @@ import androidx.appcompat.app.AppCompatActivity
import ru.touchin.roboswag.core.log.Lc import ru.touchin.roboswag.core.log.Lc
import ru.touchin.roboswag.core.log.LcGroup import ru.touchin.roboswag.core.log.LcGroup
import ru.touchin.roboswag.navigation_base.fragments.LifecycleLoggingObserver import ru.touchin.roboswag.navigation_base.fragments.LifecycleLoggingObserver
import ru.touchin.roboswag.navigation_viewcontroller.keyboard_resizeable.KeyboardBehaviorDetector import ru.touchin.roboswag.navigation_base.keyboard_resizeable.KeyboardBehaviorDetector
/** /**
* Created by Gavriil Sitnikov on 08/03/2016. * Created by Gavriil Sitnikov on 08/03/2016.

View File

@ -4,8 +4,6 @@ import android.content.Context
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.os.Bundle import android.os.Bundle
import android.os.Parcel
import android.os.Parcelable
import android.view.View import android.view.View
import androidx.annotation.ColorInt import androidx.annotation.ColorInt
import androidx.annotation.ColorRes import androidx.annotation.ColorRes
@ -15,30 +13,12 @@ import androidx.annotation.LayoutRes
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import ru.touchin.roboswag.navigation_base.BuildConfig
open class BaseFragment<TActivity : FragmentActivity, TState : Parcelable>(@LayoutRes layoutRes: Int) : Fragment(layoutRes) { open class BaseFragment<TActivity : FragmentActivity> : Fragment {
companion object { constructor() : super()
private const val BASE_FRAGMENT_STATE_EXTRA = "BASE_FRAGMENT_STATE_EXTRA"
fun args(state: Parcelable?): Bundle = Bundle().also { it.putParcelable(BASE_FRAGMENT_STATE_EXTRA, state) } constructor(@LayoutRes layoutRes: Int) : super(layoutRes)
// This method used to check unique state of each fragment.
// If two fragments share same class for state, you should not pass state instance of current fragment to the one you transition to
private fun <T : Parcelable> reserialize(parcelable: T): T {
var parcel = Parcel.obtain()
parcel.writeParcelable(parcelable, 0)
val serializableBytes = parcel.marshall()
parcel.recycle()
parcel = Parcel.obtain()
parcel.unmarshall(serializableBytes, 0, serializableBytes.size)
parcel.setDataPosition(0)
val result = parcel.readParcelable<T>(Thread.currentThread().contextClassLoader) ?: throw IllegalStateException("It must not be null")
parcel.recycle()
return result
}
}
protected val view: View protected val view: View
@JvmName("requireViewKtx") get() = requireView() @JvmName("requireViewKtx") get() = requireView()
@ -49,21 +29,10 @@ open class BaseFragment<TActivity : FragmentActivity, TState : Parcelable>(@Layo
protected val context: Context protected val context: Context
@JvmName("requireContextKtx") get() = requireContext() @JvmName("requireContextKtx") get() = requireContext()
protected lateinit var state: TState
private set
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setHasOptionsMenu(true) setHasOptionsMenu(true)
state = savedInstanceState?.getParcelable<TState>(BASE_FRAGMENT_STATE_EXTRA)
?: arguments?.getParcelable(BASE_FRAGMENT_STATE_EXTRA)
?: throw IllegalStateException("Fragment state can't be null")
if (BuildConfig.DEBUG) {
state = reserialize(state)
}
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -72,11 +41,6 @@ open class BaseFragment<TActivity : FragmentActivity, TState : Parcelable>(@Layo
lifecycle.addObserver(LifecycleLoggingObserver(this)) lifecycle.addObserver(LifecycleLoggingObserver(this))
} }
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putParcelable(BASE_FRAGMENT_STATE_EXTRA, state)
}
fun <T : View> findViewById(@IdRes id: Int): T = view.findViewById(id) fun <T : View> findViewById(@IdRes id: Int): T = view.findViewById(id)
@ColorInt @ColorInt

View File

@ -0,0 +1,55 @@
package ru.touchin.roboswag.navigation_base.fragments
import android.os.Bundle
import android.os.Parcel
import android.os.Parcelable
import androidx.annotation.LayoutRes
import androidx.fragment.app.FragmentActivity
import ru.touchin.roboswag.navigation_base.BuildConfig
open class FragmentWithState<TActivity : FragmentActivity, TState : Parcelable>(
@LayoutRes layoutRes: Int
) : BaseFragment<TActivity>(layoutRes) {
companion object {
private const val BASE_FRAGMENT_STATE_EXTRA = "BASE_FRAGMENT_STATE_EXTRA"
fun args(state: Parcelable?): Bundle = Bundle().also { it.putParcelable(BASE_FRAGMENT_STATE_EXTRA, state) }
// This method used to check unique state of each fragment.
// If two fragments share same class for state, you should not pass state instance of current fragment to the one you transition to
private fun <T : Parcelable> reserialize(parcelable: T): T {
var parcel = Parcel.obtain()
parcel.writeParcelable(parcelable, 0)
val serializableBytes = parcel.marshall()
parcel.recycle()
parcel = Parcel.obtain()
parcel.unmarshall(serializableBytes, 0, serializableBytes.size)
parcel.setDataPosition(0)
val result = parcel.readParcelable<T>(Thread.currentThread().contextClassLoader) ?: throw IllegalStateException("It must not be null")
parcel.recycle()
return result
}
}
protected lateinit var state: TState
private set
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
state = savedInstanceState?.getParcelable<TState>(BASE_FRAGMENT_STATE_EXTRA)
?: arguments?.getParcelable(BASE_FRAGMENT_STATE_EXTRA)
?: throw IllegalStateException("Fragment state can't be null")
if (BuildConfig.DEBUG) {
state = reserialize(state)
}
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putParcelable(BASE_FRAGMENT_STATE_EXTRA, state)
}
}

View File

@ -1,4 +1,4 @@
package ru.touchin.roboswag.navigation_viewcontroller.keyboard_resizeable package ru.touchin.roboswag.navigation_base.keyboard_resizeable
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat