当我旋转屏幕时,我从 Activity 发送到 Fragment 的包仍然存在。为什么?

The bundle i sent to Fragment from Activity is still alive when i rotate the screen. WHY?

我有一个 Activity,还有一个 TextView、一个 EditText、一个按钮和一个 FrameLayout。 我在 EditText 中输入了一些词,然后按下发送按钮,Activity 的 TextView 将随着该词发生变化,同时生成一个包含该词的包并开始一个 Fragment。 在片段的 onCreate 方法中,我可以获得刚从 Activity 发送的参数。 然后我把这个词放在 Fragment 的 TextView 中。 但是当我旋转屏幕时问题就开始了。

我了解到屏幕旋转时所有属性都会重置。 因此,Activity 的 TextView 被重置。没关系。我就知道。 但是 Fragment 的 TextView 甚至还活着! 它没有重置。

为什么?

我检查了日志。这太奇怪了。 这是App的全部订单。

2020-09-17 11:53:16.569 15207-15207/com.example.screenlotateex D/TEST: Activity onCreate()

2020-09-17 11:53:33.541 15207-15207/com.example.screenlotateex D/TEST:从 Activity

发送 Bundle

2020-09-17 11:53:33.623 15207-15207/com.example.screenlotateex D/TEST:片段 onCreate()

2020-09-17 11:53:33.623 15207-15207/com.example.screenlotateex D/TEST:从 Activity 获取 Bundle:现在正在下雨。

2020-09-17 11:53:37.331 15207-15207/com.example.screenlotateex D/TEST: Activity onPause()

2020-09-17 11:53:37.340 15207-15207/com.example.screenlotateex D/TEST: Activity onStop()

2020-09-17 11:53:37.366 15207-15207/com.example.screenlotateex D/TEST: 片段 onDestroyView()

2020-09-17 11:53:37.378 15207-15207/com.example.screenlotateex D/TEST:片段 onDestroy()

2020-09-17 11:53:37.378 15207-15207/com.example.screenlotateex D/TEST:片段 onDetach()

2020-09-17 11:53:37.381 15207-15207/com.example.screenlotateex D/TEST: Activity onDestroy()

2020-09-17 11:53:37.526 15207-15207/com.example.screenlotateex D/TEST: 片段 onCreate()

2020-09-17 11:53:37.526 15207-15207/com.example.screenlotateex D/TEST:从 Activity 获取 Bundle:现在正在下雨。

2020-09-17 11:53:37.780 15207-15207/com.example.screenlotateex D/TEST: Activity onCreate()

为什么我没有再次按下按钮时片段的onCreate 方法自动运行? 最奇怪的是片段的 onCreate 在 activity 的 onCreate 之前开始!!! 而且捆绑包还活着!好可怕。

这是我的代码。

Activity

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    Log.d("TEST", "Activity onCreate()")

    button.setOnClickListener {
        text.text = editText.text.toString()
        val bundle = Bundle()
        Log.d("TEST", "send Bundle from Activity")
        bundle.putString("key", editText.text.toString())
        val fragment = TestFragment()
        fragment.arguments = bundle
        supportFragmentManager.beginTransaction().replace(R.id.frameLayout, fragment).commit()
    }
}

override fun onPause() {
    super.onPause()
    Log.d("TEST", "Activity onPause()")
}

override fun onStop() {
    super.onStop()
    Log.d("TEST", "Activity onStop()")
}

override fun onDestroy() {
    super.onDestroy()
    Log.d("TEST", "Activity onDestroy()")
}
}

Activity XML

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<TextView
    android:id="@+id/text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Hello World!"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<EditText
    android:id="@+id/editText"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toBottomOf="@id/text"
    android:hint="write here."/>

<Button
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="SEND"
    app:layout_constraintTop_toBottomOf="@id/editText"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent" />

<FrameLayout
    android:id="@+id/frameLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

片段

class TestFragment : Fragment() {

private var text: String? = null

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    Log.d("TEST", "Fragment onCreate()")
    arguments?.let {
        text = it.getString("key")
        Log.d("TEST", "get Bundle from Activity : $text")
    }
}

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                          savedInstanceState: Bundle?): View? {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_test, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    frag_text.text = text
}

override fun onDestroyView() {
    super.onDestroyView()
    Log.d("TEST", "Fragment onDestroyView()")
}

override fun onDestroy() {
    super.onDestroy()
    Log.d("TEST", "Fragment onDestroy()")
}

override fun onDetach() {
    super.onDetach()
    Log.d("TEST", "Fragment onDetach()")
}

}

片段XML

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".TestFragment">

<TextView
    android:id="@+id/frag_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/hello_blank_fragment"
    android:textColor="@color/colorAccent"
    android:textSize="30sp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.564"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="0.243" />
  </androidx.constraintlayout.widget.ConstraintLayout>

我真的希望有人能帮助我。

所有 Android 的核心部分是保存状态,让用户回到与旋转设备、切换到另一个应用程序并切换回来等后完全相同的状态。这是为什么 类 像 Activity 有 onSaveInstanceState() 方法。

作为此库的一部分,例如 Fragments,会自动插入这些方法。这意味着 FragmentManager 会自动保存和恢复其状态 - 包括存在的片段及其参数包。

对于片段,它们会作为对 super.onCreate() 调用的一部分进行恢复 - 如果您在 super.onCreate() 之前移动了日志消息,您会看到它 运行在片段的 onCreate().

之前