Android Code Club - Fragment
Android
Fragment
Kotlin
Java
本週三去參加 Android Developer 開發讀書會 主辦的 Android Code Club
2020-08-19 Week 3 - Activity and Fragment
當天講者有提到說,如果 Fragment 被系統回收,系統再次生成這一個 fragment 只會用預設的 initial
這是一個很特別的情境,通常不會在其他語言也遇到,所以寫一篇文章來記錄整個狀況
=== 這是分隔線 ===
如我們剛才所說,系統只會用 default 的 initial func 去建立 fragment
可以在 Fragment 的 class Source code 裡面看到
It is strongly recommended to supply arguments with {@link #setArguments} * and later retrieved by the Fragment with {@link #getArguments}. These arguments * are automatically saved and restored alongside the Fragment.
/**
* Constructor used by the default {@link FragmentFactory}. You must
* {@link FragmentManager#setFragmentFactory(FragmentFactory) set a custom FragmentFactory}
* if you want to use a non-default constructor to ensure that your constructor
* is called when the fragment is re-instantiated.
*
* <p>It is strongly recommended to supply arguments with {@link #setArguments}
* and later retrieved by the Fragment with {@link #getArguments}. These arguments
* are automatically saved and restored alongside the Fragment.
*
* <p>Applications should generally not implement a constructor. Prefer
* {@link #onAttach(Context)} instead. It is the first place application code can run where
* the fragment is ready to be used - the point where the fragment is actually associated with
* its context. Some applications may also want to implement {@link #onInflate} to retrieve
* attributes from a layout resource, although note this happens when the fragment is attached.
*/
public Fragment() {
initLifecycle();
}
既然官方強烈的建議我們要這樣做,那就照著做比較沒問題
通常我們為了方便,當然會建立 BaseFragment 做好一些事,方便使用
也會使用 kotlin 的特性,保證某些變數必然要被傳進來
like this
abstract class TestBaseFragment(@LayoutRes private val layout: Int) : Fragment() {
// Do Something
}
class TestSubFragment private constructor(private val id: String) : TestBaseFragment(
R.layout.xxxx
) {
companion object {
fun newInstance(id: String) = TestSubFragment(id = id)
}
}
所以,這樣的寫法,在 Fragment 被系統回收後再生,就會因為 id 沒有值,出現非我們期望的結果
甚至是 Crash
為了避免出現非我們預期的結果,或者是 Crash,我們就需要換種寫法
class TestSubFragment private constructor() : TestBaseFragment(
R.layout.xxxx
) {
private val id: String = arguments?.getString("id", "") ?: ""
companion object {
fun newInstance(id: String): TestSubFragment {
val f = TestSubFragment()
val args = Bundle()
args.putString("id", id)
f.arguments = args
return f
}
}
}
這樣就可以避開這一個奇怪的坑(Android 真是一個神奇的平台)
打完收工!