首页 > 解决方案 > Fragment onCreate(), onCreateView() & onActivityCreated() 在创建父 Activity 时都调用了两次

问题描述

我有一个带有 3 个子片段的 Activity - 一次只显示 1 个。我正在使用 BottomNavigationView 在子片段之间切换。显示的初始子片段GameFragment(), 是在创建活动时膨胀的,通过supportFragmentManager.beginTransaction().add()它添加到我fragment_layout的 xml 中的容器中FrameLayout

这应该是创建 Fragment 的唯一时间。但是,我的日志语句显示:

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

我的片段的onCreate(), onCreateView()&onActivityCreated()在活动开始时被调用两次。

主要活动:

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();
    }

分段

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)
    }

片段游戏.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" />

知道这是为什么吗?

PS:我可以在片段之间成功切换,但是onSaveInstanceState()从未调用过(例如在我的GameFragment()上面)。onSaveInstanceState()仅当我离开活动并返回时才调用我的片段(当时没有进行片段事务)。不确定这是否与根本问题有任何关系。

标签: androidxmlandroid-fragmentskotlin

解决方案


推荐阅读