TL : 데이터 바인딩과 함께 사용 된 레이아웃이 EditText
이고 android:text
에 대한 바인딩 표현식이있는 경우 바인딩 표현식은 명시 적으로 바인딩 평가를 트리거하지 않더라도 저장된 인스턴스 상태 값을 덮어 씁니다. 구성 변경 이전에 사용자가 입력 한 내용이 지워집니다. 이 문제를 어떻게 해결하여 구성 변경시 저장된 인스턴스 상태 값이 사용됩니까?저장된 인스턴스 상태를 사용하기 위해 데이터 바인딩을 얻는 방법은 무엇입니까?
public class Model {
public String getTitle() {
return("Title");
}
}
그리고 우리는 Model
이 참조하는 레이아웃이 있습니다 :
우리는 바보
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>
참고; 우리는 그걸 약간 알아챌거야.
레이아웃은 동적 조각에 사용된다 : 우리는 바인딩에 Model
를 밀어 어디서나 setModel()
를 호출하지 않는
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());
}
}
참고. MainBinding
(위에 표시된 main.xml
레이아웃의 경우)은 레이아웃을 팽창시키는 데 사용됩니다.
이 코드 (FragmentActivity
은 FormFragment
으로 설정해야 함)는 저장된 인스턴스 상태를 올바르게 사용합니다. 사용자가 EditText
에 무언가를 입력 한 다음 화면을 회전 시키면 새로 작성된 EditText
에 입력 된 텍스트가 표시됩니다.
자, android:text
에 대한 바인딩 식을 추가 할 레이아웃을 변경할 수 있습니다 : 사용자 유형 EditText
에 뭔가가 화면을 회전하면
<?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
가 비어 있습니다. 바인딩 표현식은 저장된 인스턴스 상태에서 복원 된 프레임 워크를 덮어 씁니다.
이것은 바인딩에 setModel()
을 호출하지 않는다는 사실에도 불구하고 나온 것입니다. 어디에서 setModel()
이라는 바인딩을 호출하면 모델의 데이터로 EditText
내용을 대체 할 수 있는지 확인할 수 있습니다. 그러나 나는 그렇게하지 않는다.
정식 기기 (Google Pixel, Android 8.0)와 생태계 기기 (Samsung Galaxy S8, Android 7.1)에서이 동작을 재현 할 수 있습니다.
이것은 상태를 직접 저장하고 어느 시점에서 복원하여 "수동으로"해결할 수 있습니다. 예를 들어, 여러 의견은 양방향 바인딩을 제안했지만 다른 디자인 목표 (예 : 불변 모델 객체)와는 반대 방향으로 실행됩니다. 이것은 데이터 바인딩의 근본적인 제한 인 것처럼 보입니다. 그래서 내가 놓친 뭔가가 저장된 인스턴스 상태를 자동으로 사용하도록 구성 할 수 있기를 바랍니다.
'android : text = "@ {model.title}"'단방향 데이터 바인딩을 사용하고 있거나 오타이고 양방향 데이터 바인딩을 의미합니까? – pskink
@pskink : 단방향 바인딩을 사용하고 있습니다. 양방향 바인딩은 가능한 또 다른 해결 방법이 될 수 있습니다.하지만이 문제와 관련하여 실제 앱에서 사용하지 않는 것이 좋습니다. 양방향 바인딩은 "상태를 스스로 저장하고 어느 시점에서 복원"하는 또 다른 변형입니다. – CommonsWare
양방향 바인딩을 사용하여 자동 상태 복원을 사용하는 [관련 답변] (https://stackoverflow.com/a/46086436/1676363)을 참조하십시오. – ianhanniballake