Android 弹出片段后,所有EditExt都将替换为相同的值

Android 弹出片段后,所有EditExt都将替换为相同的值,android,android-fragments,fragment-backstack,Android,Android Fragments,Fragment Backstack,我有一个奇怪的问题,我有2个片段,在第一个片段中,我有一些自定义的EditText,还有一个按钮用第二个片段替换它(addToBackStack=true),然后在第二个片段中,我尝试使用popBackStack()返回到第一个片段,问题发生了,所有自定义EditText都具有相同的值 下面是我所有的代码 第一片段 第二片段 fragment_first.xml layout_custom_view.xml 任何响应都将不胜感激。您不是在添加后堆栈,而是在替换,尝试打开第二个片段,这将保持

我有一个奇怪的问题,我有2个片段,在第一个片段中,我有一些自定义的
EditText
,还有一个按钮用第二个片段替换它(
addToBackStack
=true),然后在第二个片段中,我尝试使用
popBackStack()
返回到第一个片段,问题发生了,所有自定义
EditText
都具有相同的值

下面是我所有的代码

第一片段

第二片段

fragment_first.xml

layout_custom_view.xml



任何响应都将不胜感激。

您不是在添加后堆栈,而是在替换,尝试打开第二个片段,这将保持第一个片段的完整状态并在堆栈中

btn_next.setOnClickListener {
            val transaction = requireActivity().supportFragmentManager!!.beginTransaction()
                .add(R.id.contentFrame, SecondFragment(), "")
            commitTransaction(transaction, true, -1)
        }

另外,您的两个
EditText
都有相同的id
android:id=“@+id/edt”
,因此运行
findViewById
的合成器函数将指向
EditText

的相同对象。我将尝试在布局中为每个自定义视图添加不同的id。比如:

com.sogia.replacefragmentdemo.CustomView
    android:id="@+id/custom1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
/>

com.sogia.replacefragmentdemo.CustomView
    android:id="@+id/custom2"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    />

拥有相同的id可能是一个问题,因为管理状态可能会变得混乱。 检查此项以获得解决方案:
最后我找到了根本原因和解决方案, 感谢@abhradeep ghosh、@Eselfar、@madscitector和其他回复此帖子的人

原因:视图ID应该是唯一的!否则,您的状态将被具有相同ID的另一个视图覆盖。在我的情况下,我有两个ID为
@ID/edt
的视图,因此我的状态容器仅包含它的一个实例—以状态存储过程中最后出现的为准

这是我的解决方案,(来自)

首先,为保存视图状态创建新类

class SavedState(superState: Parcelable) : View.BaseSavedState(superState) {
    var childrenStates: SparseArray<Any>? = null

    override fun writeToParcel(out: Parcel, flags: Int) {
        super.writeToParcel(out, flags)
        childrenStates?.let {
            out.writeSparseArray(it)
        }
    }
}

为什么您使用自定义的EditText(com.sogia.replacefragmentdemo.CustomView)而不是默认的EditText?@sebasira只是为了演示这个问题,在实际代码中,我使用了更多的视图如果您使用默认的EditText,您有相同的行为还是问题已经解决了?如果它消失了,那么问题可能在您的自定义视图中。如果错误仅出现在使用自定义视图时,您可以发布它吗?@sebasira是的,问题仅出现在我使用自定义视图时,但您可以看到我的
CustomView
,它非常清楚,我看不到任何问题我也有类似的问题,请查看我已在“commitTransaction”行的后堆栈中添加片段的答案(交易,正确,-1)’,我也认为“kotlinx.android.synthetic”是根本原因,但正如您所看到的,我的代码很清楚,我将关注这一点,并在回来时告诉您结果我有这个问题的答案,很遗憾我不能接受您的答案,因为它没有解决方案,但是,嗯,非常感谢(+1)别担心,为了知识的缘故,请把你的答案发出来。谢谢。我发了:)请看下面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <Button
        android:id="@+id/btn_back"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="back"
        />
</LinearLayout>
class CustomView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {
    init {
        inflate(context, R.layout.layout_custom_view, this)
    }
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    >
    <EditText
        android:id="@+id/edt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="input something"
        />
</LinearLayout>
btn_next.setOnClickListener {
            val transaction = requireActivity().supportFragmentManager!!.beginTransaction()
                .add(R.id.contentFrame, SecondFragment(), "")
            commitTransaction(transaction, true, -1)
        }
com.sogia.replacefragmentdemo.CustomView
    android:id="@+id/custom1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
/>

com.sogia.replacefragmentdemo.CustomView
    android:id="@+id/custom2"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    />
class SavedState(superState: Parcelable) : View.BaseSavedState(superState) {
    var childrenStates: SparseArray<Any>? = null

    override fun writeToParcel(out: Parcel, flags: Int) {
        super.writeToParcel(out, flags)
        childrenStates?.let {
            out.writeSparseArray(it)
        }
    }
}
@Suppress("UNCHECKED_CAST")
    public override fun onSaveInstanceState(): Parcelable? {
        val superState = super.onSaveInstanceState()
        val ss = SavedState(superState)
        ss.childrenStates = SparseArray()
        for (i in 0 until childCount) {
            getChildAt(i).saveHierarchyState(ss.childrenStates as SparseArray<Parcelable>)
        }
        return ss
    }

    @Suppress("UNCHECKED_CAST")
    public override fun onRestoreInstanceState(state: Parcelable) {
        val ss = state as SavedState
        super.onRestoreInstanceState(ss.superState)
        for (i in 0 until childCount) {
            getChildAt(i).restoreHierarchyState(ss.childrenStates as SparseArray<Parcelable>)
        }
    }

    override fun dispatchSaveInstanceState(container: SparseArray<Parcelable>) {
        dispatchFreezeSelfOnly(container)
    }

    override fun dispatchRestoreInstanceState(container: SparseArray<Parcelable>) {
        dispatchThawSelfOnly(container)
    }