android 为什么我的recyclerview不显示任何数据?

t40tm48m  于 2023-03-06  发布在  Android
关注(0)|答案(1)|浏览(357)

我有一个简单的搜索应用程序。API调用正确地获取对象并将其加载到movies. list中。我从viewModel中观察此列表并将其传递给适配器。(大多数时候为空)然后适配器连接到recyclerview,...它不会显示任何内容。
我尝试使用viewmodelFactory对ViewModel初始化进行调整-可能是列表加载速度慢于适配器发布的速度。我尝试在等待时制作加载动画,但不起作用
结果片段

package com.dragos.moviesearch.ui.main

import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import com.dragos.moviesearch.databinding.FragmentResultsBinding
import com.dragos.moviesearch.viewmodel.MainViewModel

class ResultsFragment : Fragment() {

    private val viewModel: MainViewModel by lazy {
        ViewModelProvider(this).get(MainViewModel::class.java)
    }

    private var myadapter = ResultsAdapter()

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        val binding = FragmentResultsBinding.inflate(inflater)
        binding.lifecycleOwner = this

        viewModel.moviesList.observe(viewLifecycleOwner) {
            if (it != null){
                println("dra avem urmatoarele filme atasate la adaptor: " + it)
                myadapter.info = it
                myadapter.notifyDataSetChanged()
                for(i in 0..5){
                    println("dra avem urmatoarele filme in resultsfragment la onCreate: " + (viewModel.moviesList.value?.get(i)))
                }
            }
        }

        binding.resultsRecyclerview.adapter = myadapter
        binding.resultsRecyclerview.layoutManager = LinearLayoutManager(context)

        return binding.root
    }
}

主视图模型

package com.dragos.moviesearch.viewmodel

import androidx.lifecycle.*
import com.dragos.moviesearch.data.Movie
import com.dragos.moviesearch.data.MoviesList
import com.dragos.moviesearch.repository.DataRepository
import kotlinx.coroutines.launch
enum class MovieApiStatus { LOADING, ERROR, DONE }

class MainViewModel : ViewModel() {

    private val repository: DataRepository = DataRepository
    private var _moviesList = MutableLiveData<List<Movie>>()
    val moviesList: LiveData<List<Movie>>
        get() = _moviesList

    private val _status = MutableLiveData<MovieApiStatus>()
    val status: LiveData<MovieApiStatus> = _status

    private var _query = MutableLiveData<String>()
    val query: LiveData<String> = _query

    fun getMovieInfo() {
        viewModelScope.launch {
            _status.value = MovieApiStatus.LOADING
            try {
                _moviesList.value = _query.value?.let { repository.getMovieInfo(it)}
                _status.value = MovieApiStatus.DONE
                println("dra here we have the movie list at done: " + _moviesList.value)
            } catch (e: Exception) {
                _status.value = MovieApiStatus.ERROR
                _moviesList.value = ArrayList()
            }
        }
    }

    fun updateQuery(rawInputQuery: String) {
        _query.value = rawInputQuery.replace(" ","+")
        println("dra query-ul este: " + _query.value)
    }
}

结合衔接子

package com.dragos.moviesearch.utils

import android.os.Build.VERSION_CODES.M
import android.view.View
import android.widget.ImageView
import androidx.core.net.toUri
import androidx.databinding.BindingAdapter
import com.dragos.moviesearch.R
import coil.load
import com.dragos.moviesearch.viewmodel.MovieApiStatus

@BindingAdapter("showPhoto")
fun bindImage(imgView: ImageView, imgUrl: String?) {
    imgUrl?.let {
        val imgUri = imgUrl.toUri().buildUpon().scheme("https").build()
        imgView.load(imgUri) {
            placeholder(R.drawable.loading_animation)
            error(R.drawable.ic_broken_image)
        }
    }
}

@BindingAdapter("movieApiStatus")
fun bindStatus(statusImageView: ImageView, status: MovieApiStatus?) {
    when (status) {
        MovieApiStatus.LOADING -> {
            statusImageView.visibility = View.VISIBLE
            statusImageView.setImageResource(R.drawable.loading_animation)
        }
        MovieApiStatus.ERROR -> {
            statusImageView.visibility = View.VISIBLE
            statusImageView.setImageResource(R.drawable.ic_connection_error)
        }

        else -> {statusImageView.visibility = View.GONE}
    }}

结果适配器

package com.dragos.moviesearch.ui.main

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.dragos.moviesearch.data.Movie
import com.dragos.moviesearch.data.MoviesList
import com.dragos.moviesearch.databinding.MovieItemBinding
import com.dragos.moviesearch.utils.bindImage

class ResultsAdapter: RecyclerView.Adapter<ResultsAdapter.MovieHolder>() {

    var info: List<Movie> = listOf()

    class MovieHolder(private var binding: MovieItemBinding): RecyclerView.ViewHolder(binding.root) {

        fun bind(movie: Movie){
            binding.itemTitle.text = movie.show.name
            binding.itemGenres.text = movie.show.genres.joinToString(separator = " ")
            bindImage(binding.movieImg, movie.show.image.medium)
            binding.executePendingBindings()
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MovieHolder {
        return MovieHolder(MovieItemBinding.inflate(LayoutInflater.from(parent.context)))
    }

    override fun onBindViewHolder(holder: MovieHolder, position: Int) {
        holder.bind(info[position])
    }

    override fun getItemCount() = info.size
}

fragment_results.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">

    <data>
        <variable
            name="viewModel"
            type="com.dragos.moviesearch.viewmodel.MainViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/secondaryTextColor">

        <EditText
            android:id="@+id/searchMovie"
            style="@style/editTextStyle"
            android:layout_marginTop="20dp"
            android:layout_marginEnd="17dp"
            android:background="@drawable/round_corners_shape_empty"
            android:hint="@string/search"
            android:textColor="@color/whiteText"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <ImageView
            android:id="@+id/magnifierButton"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_marginStart="5dp"
            app:layout_constraintBottom_toBottomOf="@+id/searchMovie"
            app:layout_constraintStart_toEndOf="@+id/searchMovie"
            app:layout_constraintTop_toTopOf="@+id/searchMovie"
            app:srcCompat="@drawable/baseline_search_24" />

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/resultsRecyclerview"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_marginTop="10dp"
    app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/searchMovie" />

        <ImageView
            android:id="@+id/status_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:movieApiStatus="@{viewModel.status}" />

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

谢谢大家!

iyfjxgzm

iyfjxgzm1#

对于标准实施:
据我所知,在您的MainViewModel类中,您需要在从API提取数据后调用ResultsAdapter.notifyDataSetChanged() ...
您还可以(最好使用DiffUtil以提高效率)。
对于实时数据:
你可以通过一个观察者来完成这个任务,观察者会接收修改,然后更新RecyclerView的列表。有很多关于这个主题的指南和博客,包括update RecyclerView with Android LiveData

相关问题