TL; DR:如果使用數據綁定使用的佈局有一個EditText
,並且對於android:text
綁定表達式,綁定表達式將覆蓋保存的實例狀態值......即使我們沒有明確觸發約束力的評估。用戶在配置更改前輸入的內容被清除。我們如何解決這個問題,以便在配置更改時使用保存的實例狀態值?我們如何獲取數據綁定以使用保存的實例狀態?
我們有一個愚蠢的Model
:
public class Model {
public String getTitle() {
return("Title");
}
}
我們有一個佈局引用Model
:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="model"
type="com.commonsware.databindingstate.Model" />
</data>
<android.support.constraint.ConstraintLayout xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.commonsware.databindingstate.MainActivity">
<EditText android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:inputType="text"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
</layout>
注意,這個佈局沒有綁定表達式;我們會做一點。
的佈局是在動態片段中使用:
public class FormFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return(MainBinding.inflate(inflater, container, false).getRoot());
}
}
請注意,我們不是要求setModel()
任何地方的Model
推入約束力。 MainBinding
(上面顯示的main.xml
佈局)僅用於充氣佈局。
此代碼(使用合適的FragmentActivity
來設置FormFragment
)可以正確使用保存的實例狀態。如果用戶鍵入的東西到EditText
,然後旋轉屏幕,新近重新EditText
顯示輸入型文本。
現在,讓我們改變佈局,添加綁定表達式android:text
:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="model"
type="com.commonsware.databindingstate.Model" />
</data>
<android.support.constraint.ConstraintLayout xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.commonsware.databindingstate.MainActivity">
<EditText android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:inputType="text"
android:text="@{model.title}"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
</layout>
現在,如果用戶鍵入的東西到EditText
和旋轉屏幕,新近重新EditText
是空的。綁定表達式覆蓋從已保存實例狀態恢復的任何框架。
這涉及儘管我不是呼籲結合setModel()
。我當然能看到,如果我在結合稱爲setModel()
其中,將與來自模型的數據替換EditText
內容。但我沒有那樣做。
我可以重現兩種官方設備(谷歌像素,安卓8.0)和生態系統設備(三星Galaxy S8,安卓7.1)此行爲。
這可以通過自己保存狀態並在某個時刻恢復它來解決「手動」問題。例如,多個註釋建議使用雙向綁定,但與其他設計目標(例如不可變模型對象)背道而馳。這似乎是數據綁定的一個相當根本的限制,所以我希望有一些我錯過了,我可以配置自動使用保存的實例狀態。
在'機器人:文本=「@ {} model.title」'您使用的單向數據綁定,或者它是一個錯字和你的意思是雙向數據綁定? – pskink
@pskink:我正在使用單向綁定。雙向綁定將是另一種可能的解決方法,但我不希望在真正的應用程序中使用該問題。雙向綁定是「自己拯救國家並在某個時候恢復」的另一種變體。 – CommonsWare
查看使用雙向綁定自動狀態恢復的[相關答案](https://stackoverflow.com/a/46086436/1676363)。 – ianhanniballake