I have an Activity with 3 child fragments - with only 1 showing at a time. I'm using a BottomNavigationView to switch between child fragments. The initial child fragment shown, GameFragment()
, is inflated when the activity is created via supportFragmentManager.beginTransaction().add()
which is added to my container fragment_layout
in my xml FrameLayout
.
This should be the only time the Fragment is created. However, my Log statements show:
D/LifecycleChange: Activity Created
D/LifecycleChange: onCreate GameFragment
D/LifecycleChange: onCreateView GameFragment
D/LifecycleChange: onActivityCreated
D/LifecycleChange: onCreate GameFragment
D/LifecycleChange: onCreateView GameFragment
D/LifecycleChange: onActivityCreated
that my fragment's onCreate()
, onCreateView()
& onActivityCreated()
are called twice when the activity starts.
Main activity:
class TruthOrDare : FragmentActivity(), BottomNavigationView.OnNavigationItemSelectedListener {
override fun onNavigationItemSelected(item: MenuItem): Boolean {
val selectedFragment = when (item.itemId){
R.id.action_leaderboards -> LeaderboardsFragment()
R.id.action_options -> OptionsFragment()
else -> GameFragment()
}
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.fragment_layout, selectedFragment)
transaction.addToBackStack(null)
transaction.commit()
return true
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_truth_or_dare)
Log.d("LifecycleChange", "Activity Created")
bottomNav_truthordare.setOnNavigationItemSelectedListener(this)
bottomNav_truthordare.selectedItemId = R.id.action_game
if (savedInstanceState != null) {
Log.d("LifecycleChange", "Activity onSaveInstanceState is not null")
return
}
val firstFragment = GameFragment()
firstFragment.arguments = intent.extras
supportFragmentManager.beginTransaction().add(R.id.fragment_layout, firstFragment).commit();
}
Fragment
class GameFragment : Fragment(), View.OnClickListener {
override fun onSaveInstanceState(outState: Bundle) {
Log.d("LifecycleChange", "onSaveInstanceState GameFragment")
super.onSaveInstanceState(outState)
var truthdareisvisible = true
if (truth.visibility != View.VISIBLE){
truthdareisvisible = false
}
outState.putBoolean("truthdareisvisibile", truthdareisvisible)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
if (savedInstanceState != null){
Log.d("LifecycleChange", "onActivityCreated savedInstanceState is not null")
val truthdareisvisible = savedInstanceState.getBoolean("truthdareisvisibile")
if (truthdareisvisible) truth.visibility == View.VISIBLE
}
Log.d("LifecycleChange", "onActivityCreated")
super.onActivityCreated(savedInstanceState)
val bundle = this.arguments
if (bundle != null){
playersinfo = bundle.getParcelable("playersinfo")
players = playersinfo.players
tempPlayers = ArrayList(players)
numberOfPlayers = players.size
_chosenPlayer = tempPlayers[Random.nextInt(numberOfPlayers)]
chosenPlayer.text = _chosenPlayer.name
truth.setOnClickListener(this)
dare.setOnClickListener(this)
complete.setOnClickListener(this)
forfeit.setOnClickListener(this)
fadeIn(chosenPlayer, 3000)
writeText(chosenPlayer, "...", 200)
Handler().postDelayed({showViews(listOf(truth, or, dare), 2000)}, 2000)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
if (savedInstanceState != null) {
Log.d("LifecycleChange", "onCreate GameFragment is not null")
return
}
Log.d("LifecycleChange", "onCreate GameFragment")
super.onCreate(savedInstanceState)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
Log.d("LifecycleChange", "onCreateView GameFragment")
return inflater.inflate(R.layout.fragment_game, container, false)
}
fragment_game.xml
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar_truthordare"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimaryDark"
android:elevation="4dp"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
app:layout_constraintTop_toTopOf="parent"
app:popupTheme="@color/colorPrimaryDark"
app:title="Level 1" />
<FrameLayout
android:id="@+id/fragment_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/bottomNav_truthordare" android:layout_below="@id/toolbar_truthordare">
</FrameLayout>
<android.support.design.widget.BottomNavigationView
android:id="@+id/bottomNav_truthordare"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimaryDark"
app:itemIconTint="@color/bottom_nav_items"
app:itemTextColor="@color/bottom_nav_items"
android:layout_alignParentBottom="true"
app:menu="@menu/menu" />
Any idea why this is?
PS: I can successfully switch between fragments, however onSaveInstanceState()
is never called (e.g. in my GameFragment()
above). onSaveInstanceState()
in my fragment is only called when I leave the activity and come back (without making a fragment transaction in that time). Not sure if this is related in any way to the root problem.