首页 > 解决方案 > 带/不带baseObservable的android viewmodel

问题描述

我试图在 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 的东西。

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

标签: javaandroidmvvmviewmodel

解决方案


您不能在同一个类中同时BaseObservable扩展两者。您ViewModel可以.ViewModel

您需要通过添加一个扩展自的类来使用双向数据绑定BaseObservable

在这个类中,为你需要观察的文本创建一个字段;然后用它的setter注释它的getter并在它的setter中@Bindable调用notifyPropertyChanged()

视图模型

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);
        }
    }

}

活动

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>

希望能帮到你


推荐阅读