как настроить двустороннюю привязку данных в пользовательской одежде Spinner. Я пытался, но ошибка, я не могу этого понять

#java #android #data-binding

Вопрос:

Я хочу установить Spinner remember selectedItemPosition, даже если я перезапущу свое приложение, поэтому я использую двустороннюю привязку данных и создаю пользовательский атрибут Spinner. Я использую ViewModel и SavedStateHandle для сохранения позиции. Но я не могу успешно строить. И еще один вопрос, я ищу в описании ссылки ввода здесь Я обнаружил , что платформа обеспечивает встроенную поддержку двусторонней привязки данных, введите описание изображения здесь, но когда я использовал spinner android:selectedItemPosition или android:selection, как показано, этих двух атрибутов не было.Я уже добавил зависимости :реализация «androidx.привязка данных:привязка данных-адаптеры:7.1.0-alpha02» Почему я все еще не могу использовать эти атрибуты?

Вот мой activity_main.xml:

 <?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"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <variable
            name="myViewModel"
            type="com.flag.listviewmodel.MyViewModel" />
    </data>

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

        <TextView
            android:id="@ id/textView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.185" />

        <Spinner
            android:id="@ id/spinner"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:entries="@array/minute"
            app:position="@={myViewModel.position}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

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

вот мой MainActivity.java:

 package com.flag.listviewmodel;

import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.lifecycle.SavedStateViewModelFactory;
import androidx.lifecycle.ViewModelProvider;

import android.os.Bundle;
import android.widget.Spinner;

import com.flag.listviewmodel.databinding.ActivityMainBinding;

public class MainActivity extends AppCompatActivity {
    MyViewModel myViewModel;
    ActivityMainBinding binding;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding= DataBindingUtil.setContentView(this,R.layout.activity_main);

        myViewModel= new ViewModelProvider(
                this,new SavedStateViewModelFactory(
                getApplication(),this)).get(MyViewModel.class);
        binding.setMyViewModel(myViewModel);
        binding.setLifecycleOwner(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        myViewModel.save();
    }
}
 

here is my MyViewModel.java

 package com.flag.listviewmodel;

import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import android.view.View;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.Spinner;

import androidx.annotation.NonNull;
import androidx.databinding.Bindable;
import androidx.databinding.BindingAdapter;
import androidx.databinding.InverseBindingAdapter;
import androidx.databinding.InverseBindingListener;
import androidx.databinding.Observable;
import androidx.databinding.adapters.AdapterViewBindingAdapter;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.SavedStateHandle;

/**
 * author: Administrator
 * created on: 2021/6/15 0015 上午 11:32
 * description:
 */
public class MyViewModel extends AndroidViewModel {
    SavedStateHandle handle;

    public MyViewModel(@NonNull  Application application, SavedStateHandle handle) {
        super(application);
        this.handle=handle;
        if(!handle.contains("position")){
            load();
        }
    }

    public LiveData<Integer> getPosition(){
        return handle.getLiveData("position");
    }
    public void save(){
        SharedPreferences shp=getApplication().getSharedPreferences(
                "position", Context.MODE_PRIVATE);
        SharedPreferences.Editor editor=shp.edit();
        @SuppressWarnings("ConstantConditions") int x=getPosition().getValue();
        editor.putInt("position",x);
        Log.e("MyViewModel","save(MyViewModel.java:44)" String.valueOf(x));
        editor.apply();

    }
    public void load(){
        
        SharedPreferences shp=getApplication().getSharedPreferences(
                "position",Context.MODE_PRIVATE);
        int x=shp.getInt("position",0);
        handle.set("position",x);
    }
}

 

here is my SpinnerAdapter.java:

 package com.flag.listviewmodel;

import android.view.View;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.Spinner;

import androidx.databinding.BindingAdapter;
import androidx.databinding.BindingConversion;
import androidx.databinding.InverseBindingAdapter;
import androidx.databinding.InverseBindingListener;
import androidx.databinding.adapters.AdapterViewBindingAdapter;
import androidx.lifecycle.LiveData;

/**
 * author: Administrator
 * created on: 2021/6/24 0024 下午 4:53
 * description:
 */
public class SpinnerAdapter {

    @BindingAdapter("position")
    public static void setPosition(Spinner view, int position) {
        if (view.getSelectedItemPosition() != position) {
            view.setSelection(position);
        }
    }
    @InverseBindingAdapter(attribute = "position",event = "positionAttrChanged")
    public static int getPosition(Spinner view){
        return view.getSelectedItemPosition();
    }

    @BindingAdapter(value = {"android:onItemSelected", "android:onNothingSelected",
            "positionAttrChanged" }, requireAll = false)
    public static void setOnItemSelectedListener(Spinner view,
                                                 final AdapterViewBindingAdapter.OnItemSelected selected,
                                                 final AdapterViewBindingAdapter.OnNothingSelected nothingSelected,
                                                 final InverseBindingListener attrChanged) {
        if (selected == null amp;amp; nothingSelected == null amp;amp; attrChanged == null) {
            view.setOnItemSelectedListener(null);
        } else {
            view.setOnItemSelectedListener(
                    new OnItemSelectedComponentListener(selected, nothingSelected, attrChanged));
        }
    }
    public static class OnItemSelectedComponentListener implements AdapterView.OnItemSelectedListener {
        private final AdapterViewBindingAdapter.OnItemSelected mSelected;
        private final AdapterViewBindingAdapter.OnNothingSelected mNothingSelected;
        private final InverseBindingListener mAttrChanged;
        public OnItemSelectedComponentListener(AdapterViewBindingAdapter.OnItemSelected selected,
                                               AdapterViewBindingAdapter.OnNothingSelected nothingSelected, InverseBindingListener attrChanged) {
            this.mSelected = selected;
            this.mNothingSelected = nothingSelected;
            this.mAttrChanged = attrChanged;
        }
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            if (mSelected != null) {
                mSelected.onItemSelected(parent, view, position, id);
            }
            if (mAttrChanged != null) {
                mAttrChanged.onChange();
            }
        }
        @Override
        public void onNothingSelected(AdapterView<?> parent) {
            if (mNothingSelected != null) {
                mNothingSelected.onNothingSelected(parent);
            }
            if (mAttrChanged != null) {
                mAttrChanged.onChange();
            }
        }
    }
}

 

when I build the project, AS shows me errors:

enter image description here