为什么在我使用 viewmodel 时 onClick 方法不调用 ratingBar?

Why onClick method don't call for ratingBar when i'm using viewmodel?

我有一个 recyclerView,它的每个元素都有一个 ratingBar。我尝试获取用户对每个元素的评分。

我正在使用 MVVM 架构。

现在这是我的代码:

<RatingBar
                android:id="@+id/rating"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:numStars="5"
                android:stepSize="1"
                android:onClick="@{(view) ->  listener.rateMovie(view, model)}"
                app:layout_constraintTop_toBottomOf="@id/movie_poster"
                app:layout_constraintEnd_toEndOf="@id/movie_poster"
                app:layout_constraintStart_toStartOf="@id/movie_poster"
                />


 override fun rateMovie(
        ratingBar: View,
        pickedMovieItemViewModel: PickedMovieItemViewModel
    ) {
        ratingBar as RatingBar
        val stars: Int = ratingBar.numStars
        pickedMovieItemViewModel.rating.set(stars)
    }

这是我初始化侦听器的地方:

  @BindingAdapter("rated_movies", "listener")
        @JvmStatic
        fun setItems(
            recyclerView: RecyclerView,
            items: List<PickedMovieItemViewModel>?,
            rateListener: RateListener?
        ) {
            var adapter = recyclerView.adapter
            if (adapter == null) {
                adapter = RateMoviesAdapter()
                recyclerView.adapter = adapter
                val layoutManager: RecyclerView.LayoutManager =
                    LinearLayoutManager(recyclerView.context, LinearLayoutManager.HORIZONTAL, false)
                recyclerView.layoutManager = layoutManager
            }
            if (items != null) {
                adapter as RateMoviesAdapter
                adapter.updateItems(items)
            }

            if (items != null && rateListener != null) {
                adapter as RateMoviesAdapter
                adapter.updateListener(rateListener)
            }
        }

这是 recycler-view 的适配器


class RateMoviesAdapter : RecyclerView.Adapter<RateMoviesAdapter.RateMoviesViewHolder>() {
    private lateinit var movies: List<PickedMovieItemViewModel>
    private lateinit var listener: RateListener

    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): RateMoviesViewHolder {
        val binding: ItemMovieRatedBinding = DataBindingUtil.inflate(
            LayoutInflater.from(parent.context),
            R.layout.item_movie_rated,
            parent,
            false
        )

        return RateMoviesViewHolder(binding)
    }

    override fun onBindViewHolder(holder: RateMoviesViewHolder, position: Int) {
        val item = movies[position]
        holder.bind(item, listener)
    }

    override fun getItemCount(): Int {
        return movies.size
    }

    fun update(
        movies: List<PickedMovieItemViewModel>,
        rateListener: RateListener
    ) {
        this.movies = movies
        this.listener = rateListener
        notifyDataSetChanged()
    }

    class RateMoviesViewHolder(private val binding: ItemMovieRatedBinding) :
        RecyclerView.ViewHolder(binding.root) {

        fun bind(item: PickedMovieItemViewModel, rateListener: RateListener) {
            binding.model = item
            binding.listener = rateListener
        }

    }
}

这是回收站视图所在的布局

<?xml version="1.0" encoding="utf-8"?>
<layout>

    <data>

        <variable
            name="viewModel"
            type="com.example.moviepicker.presentation.viewmodel.RateMoviesViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout 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"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".presentation.activity.RateMoviesActivity">


        <TextView
            android:id="@+id/rate_textView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/margin"
            android:gravity="center"
            android:text="@string/please_give_us_a_review_for_movies_you_have_picked"
            android:textColor="@color/red_dark"
            android:textSize="@dimen/title_size"
            android:textStyle="bold"
            app:layout_constraintTop_toTopOf="parent" />

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/rv_pickedMovies"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/top_margin"
            app:listener="@{viewModel::rateMovie}"
            app:rated_movies="@{viewModel.pickedMovies}"
            android:foregroundGravity="center"
            app:layout_constraintTop_toBottomOf="@id/rate_textView" />

        <Button
            android:id="@+id/login_button"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/top_margin"
            android:layout_marginTop="@dimen/button_top_margin"
            android:layout_marginEnd="@dimen/top_margin"
            android:layout_marginBottom="@dimen/top_margin"
            android:background="@drawable/ic_red_button"
            android:onClick="@{() -> viewModel.goMainPage()}"
            android:shadowColor="@color/black"
            android:shadowDx="1.5"
            android:shadowDy="1.3"
            android:shadowRadius="10"
            android:text="@string/next"
            android:textAllCaps="false"
            android:textColor="@color/white"
            android:textSize="@dimen/text_size"
            android:textStyle="bold"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintTop_toBottomOf="@id/rv_pickedMovies" />

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


从未调用过 rateMovie 方法。

我哪里错了?

您正在回收商的适配器中定义不同的侦听器,您需要从您的 fragment/videmodel 传递侦听器,该侦听器已在此处实现和覆盖。

YourFragment : Fragment(), RateListener {
val yourAdapter = RateMoviesAdapter(this)
}

其中“this”表示已实现的侦听器(接口),并在适配器中应用该侦听器。 然后应该工作

OnClick 事件不会在 RatingBar 视图上触发,因此我使用 setOnRatingBarChangeListener() 方法从 RatingBar 获取回调。并从 ItemViewRateBinding 中删除 android:onClick="@{(view) -> listener.rateMovie(view,model)}"。喜欢:

   fun bind(item: PickedMovieItemViewModel, rateListener: RateListener) {
        binding.model = item
        //binding.listener = rateListener
        // Click listener is not working on Rating Bar.
        binding.rating.setOnRatingBarChangeListener { ratingBar, rating, fromUser ->
            rateListener.rateMovie(ratingBar,item)
        }
    }

item_view_rate.xml

<layout>
<data>
    <variable
        name="model"
        type="com.adhoc.testapplication.PickedMovieItemViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <RatingBar
        android:id="@+id/rating"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:numStars="5"
        android:stepSize="1"

        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        />
</androidx.constraintlayout.widget.ConstraintLayout>
<!--
 android:onClick="@{(view) -> listener.rateMovie(view,model)}"
-->