android 视图模型 with/without baseObservable

android viewmodel with/without baseObservable

我试图在 android 中查看模型,所以对于 MainViewModel.java 我写了这个:


public class MainViewModel extends ViewModel {

    private String textView;
    private String editText;

    //@Bindable
    public String getTextView(){
        return textView;
    }

    private void setTextView(String value){
        textView=value;
    }

    //@Bindable
    public TextWatcher getEditTextWatcher() {
        return new TextWatcher() {
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                setTextView(s.toString());
            }
            ...
        };
    }

}

并且在 ActivityMain.xml 我写了这个:


        <TextView
            android:text="View-Model / Data-Binding"
            android:layout_width="match_parent"
            android:layout_height="40dp"/>

        <TextView
            android:id="@+id/main_text_view"
            android:text="@{mainvm.textView}"
            android:layout_width="match_parent"
            android:layout_height="40dp"/>

        <EditText
            android:id="@+id/main_edit_text"
            app:textChangeListener="@{mainvm.editTextWatcher}"
            android:layout_width="match_parent"
            android:layout_height="40dp"/>

我收到 2 个错误:

Cannot find a setter for <android.widget.EditText app:textChangeListener> that accepts parameter type 'android.text.TextWatcher'

If a binding adapter provides the setter, check that the adapter is annotated correctly and that the parameter type matches.

而且,

error: cannot find symbol class ActivityMainBindingImpl

有些文章使用 @Binable 注释扩展 BaseObservable,这不是 ViewModel 的东西。

所以我的问题是如何解决这个问题?

您需要创建 BindingAdapter 才能正确使用 DataBinding。您可以阅读更多详细信息here 例如为 EditText

创建
@BindingAdapter("addEditTextWatcher")
fun bindEditText(editText: EditText, stringTextWatcher: StringTextWatcher) {
    val string = editText.text.toString()
    stringTextWatcher.setString(editText.text.toString())
    editText.addTextChangedListener(stringTextWatcher)
}

然后你需要在你的 ViewModel 中创建一个 TextWatcher 实例来绑定它。xml 像这样

        <EditText
            android:id="@+id/main_edit_text"
            app:textChangeListener="@{mainvm.editTextWatcher}"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            addIntEditTextWatcher="@{viewModel.yourTextWatcher}"
/>

您不能在同一个 class 中同时扩展 BaseObservableViewModel。您可以在 ViewModel 中使用 ObservableFields

您需要使用 Two-way databinding by adding a class that extends from BaseObservable

在此class中,为您需要观察的文本创建一个字段;然后用 @Bindable 注释它的 getter 并在它的 setter

中调用 notifyPropertyChanged()

ViewModel

public class MainViewModel extends ViewModel {

    Observer mObserver = new Observer();

    Observer getObserver() {
        return mObserver;
    }

    public static class Observer extends BaseObservable {
        private String text;

        @Bindable
        public String getText() {
            return text;
        }

        public void setText(String value) {
            text = value;
            notifyPropertyChanged(BR.text);
        }
    }

}

Activity

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding mActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        MainViewModel mViewModel = new ViewModelProvider(this).get(MainViewModel.class);
        mActivityMainBinding.setObserver(mViewModel.getObserver());
    }
}

布局

<layout 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">

    <data>

        <variable
            name="observer"
            type="com.zain.android.twowaydatabindingedittextobservable.MainViewModel.Observer" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

        <TextView
            android:id="@+id/tvName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{observer.text}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <EditText
            android:id="@+id/etName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@={observer.text}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/tvName" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

希望能帮到你

我无缘无故地把事情弄复杂了。这是我的代码:

public class MyViewModel extends ViewModel{
     private Observable<String> data=new Observable<>("");//initializing with empty string, so that it doesn't crash
     
     public String getData(){
         return data.get();//if I return the observable itself that will become mutable, outside the class right
     }
     public void setData(String data){
          data.setValue(data);//if I accept Observable as parameter that will change reference of data, that's why passing string
     }
}

在xml中:

        <TextView
            android:id="@+id/main_text_view"
            android:text="@{myvm.data}"
            ...
        />

        <EditText
            android:id="@+id/main_edit_text"
            android:text=@{myvm.data}
            ....
        />

并像往常一样将其绑定到 Activity 或 Fragment。