Reputation: 11352
In the Android app I am developing I have a list fragment that shows a RecyclerView
of list items. The first time we open the fragment it retrieves the list from a url, but it's not going to change frequently enough to keep reloading it so I want to retain the data. As far as I can tell the Android way to do this is using the savedInstanceState
for the fragment, like this:
class ItemListFragment() {
private var itemCards: RecyclerView? = null;
public val Items: ArrayList<Item> = ArrayList<Item>()
override fun onViewStateRestored(savedInstanceState: Bundle?) {
super.onViewStateRestored(savedInstanceState)
if ( Items.size == 0 && savedInstanceState != null && savedInstanceState.containsKey("items")) {
val arrayType = object: TypeToken<Array<Item>>() {}.type
val tempItems: Array<Item> = Gson().fromJson(savedInstanceState.getString("items"), arrayType)
Items.addAll(tempItems)
}
}
}
Then I manage the states in my MainActivity
like this:
class MainActivity : AppCompatActivity() {
private lateinit var restoreBundle: HashMap<String, Bundle>
private var currentFragment = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
restoreBundle = HashMap<String, Bundle>()
setContentView(R.layout.activity_main)
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
// Handle navigation view item clicks here.
drawFragment(item.itemId)
}
private fun drawFragment(position:Int) {
val fragMan: FragmentManager = getSupportFragmentManager()
val fragmentName = getFragmentName(position)
val bundle:Bundle = restoreBundle.get(fragmentName) ?: Bundle()
var fragment: Fragment? = fragMan.getFragment(bundle, fragmentName)
if ( fragment == null ) {
fragment = ItemListFragment() as Fragment
}
val current = fragMan.findFragmentByTag(currentFragment)
if (current != null) {
val frag = getFragmentName(current.id)
val recover : Bundle = restoreBundle.get(frag) ?: Bundle()
current.onSaveInstanceState(recover)
restoreBundle.set(frag, recover);
}
if (fragmentSet) {
fragMan.beginTransaction()
.replace(R.id.main_content_fragment, fragment!!, fragmentName).commit()
} else {
fragMan.beginTransaction()
.add(R.id.main_content_fragment, fragment!!, fragmentName).commit()
}
currentFragment = fragmentName
}
}
Both of these examples have been trimmed down to what seems to me the relevant parts but the code may not be the problem so much as what I am trying to do. Basically when I switch fragment a couple of times and it calls fragMan.getFragment(bundle, fragmentName)
the bundle
contains the correct saved instance state but when I get into ItemListFragment.onViewStateRestored
( which is the next place I can put a breakpoint as far as I can tell ) the savedInstanceState
bundle is null.
Why is the bundle I am passing in not the same as the one being retrieved or what is the correct way to pass the instance state to my fragment?
Upvotes: 0
Views: 119
Reputation: 11352
I could not find a satisfactory answer to this, so I adjusted my architecture so that the models were loaded from - and stored in - their own service and made accessible as part of a companion object in my MainActivity
rather than attempting to use the Fragment architecture to pass data into the fragment. It is not clear that the latter is possible, regardless of what the documentation suggests.
Upvotes: 1