Android分页库,Recyclerview,改造,MVVM

问题描述

我正在尝试使用Android体系结构组件构建应用程序。我在应用程序中使用TMDB API。在我的应用中,用户搜索电影或连续剧并获得结果。我已经实现了这一点,但是我想从带有分页库的API中获取所有页面。 (无休止的Recyclerview)我看了几本教程,但没有得到想要的。请帮助我,我是这个Android体系结构组件的新手。先感谢您。 API结果:

enter image description here

RecyclerViewMovieAdapter

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.martiandeveloper.muuvi.R
import com.martiandeveloper.muuvi.model.Movie
import kotlinx.android.synthetic.main.recyclerview_movie_item.view.*

class RecyclerViewMovieAdapter(private val movieList: ArrayList<Movie>) :
    RecyclerView.Adapter<RecyclerViewMovieAdapter.RecyclerViewMovieViewHolder>() {

    lateinit var context: Context

    class RecyclerViewMovieViewHolder(var view: View) : RecyclerView.ViewHolder(view)

    override fun onCreateViewHolder(
        parent: ViewGroup,viewType: Int
    ): RecyclerViewMovieViewHolder {
        context = parent.context
        val view = LayoutInflater.from(context)
            .inflate(R.layout.recyclerview_movie_item,parent,false)
        return RecyclerViewMovieViewHolder(view)
    }

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

    override fun onBindViewHolder(holder: RecyclerViewMovieViewHolder,position: Int) {
        if (movieList[position].mediaType != "person") {
            if (movieList[position].mediaType == "tv") {
                val title =
                    movieList[position].originalName + " (" + movieList[position].firstAirDate?.split(
                        "-"
                    )?.get(0) + ")"
                holder.view.recyclerview_movie_item_titleMTV.text = title
            } else {
                val title =
                    movieList[position].title + " (" + movieList[position].releaseDate?.split("-")
                        ?.get(0) + ")"
                holder.view.recyclerview_movie_item_titleMTV.text = title
            }
            holder.view.recyclerview_movie_item_voteAverageMTV.text =
                movieList[position].voteAverage.toString()
            Glide.with(context)
                .load("https://image.tmdb.org/t/p/w300${movieList[position].posterPath}")
                .placeholder(R.drawable.logo1)
                .centerCrop()
                .into(holder.view.recyclerview_movie_item_posterIV)
        }
    }

    fun updateMovieList(newMovieList: List<Movie>) {
        movieList.clear()
        movieList.addAll(newMovieList)
        notifyDataSetChanged()
    }
}

Movie.kt

import com.google.gson.annotations.SerializedName

data class Movie(
    @SerializedName("original_name")
    val originalName: String?,@SerializedName("genre_ids")
    val genreIds: List<Int>?,@SerializedName("media_type")
    val mediaType: String?,@SerializedName("name")
    val name: String?,@SerializedName("origin_country")
    val originCountry: List<String>?,@SerializedName("first_air_date")
    val firstAirDate: String?,@SerializedName("original_language")
    val originalLanguage: String?,@SerializedName("id")
    val id: Int?,@SerializedName("vote_average")
    val voteAverage: Float?,@SerializedName("overview")
    val overview: String?,@SerializedName("poster_path")
    val posterPath: String?,@SerializedName("title")
    val title: String?,@SerializedName("release_date")
    val releaseDate: String?,@SerializedName("original_title")
    val originalTitle: String?)

MovieResult.kt

import com.google.gson.annotations.SerializedName

data class MovieResult(
    @SerializedName("page")
    val page: Int?,@SerializedName("total_results")
    val totalResults: Int?,@SerializedName("total_pages")
    val totalPages: Int?,@SerializedName("results")
    val results: ArrayList<Movie>?
)

MovieApi.kt

import com.martiandeveloper.muuvi.model.MovieResult
import io.reactivex.Single
import retrofit2.http.GET
import retrofit2.http.Query

interface MovieApi {
    @GET("search/multi")
    fun getMovie(
        @Query("api_key") apiKey: String,@Query("query") movie: String,@Query("page") page: Int
    ): Single<MovieResult>
}

MovieService.kt

import com.martiandeveloper.muuvi.model.MovieResult
import io.reactivex.Single
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory

const val API_KEY = "fb640042b4bc08f6f7f65fbd8573f2a9"
const val BASE_URL = "https://api.themoviedb.org/3/"

// https://api.themoviedb.org/3/search/multi?api_key=my_api_key&query=break&page=1
// https://image.tmdb.org/t/p/w342/or06FN3Dka5tukK1e9sl16pB3iy.jpg

class MovieService {

    private val api =
        Retrofit.Builder().baseUrl(BASE_URL).addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build()
            .create(MovieApi::class.java)

    fun getData(movie: String,page: Int): Single<MovieResult> {
        return api.getMovie(API_KEY,movie,page)
    }
}

AddFragment.kt

import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import android.widget.Toast
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.LinearLayoutManager
import com.martiandeveloper.muuvi.R
import com.martiandeveloper.muuvi.adapter.RecyclerViewMovieAdapter
import com.martiandeveloper.muuvi.databinding.FragmentAddBinding
import com.martiandeveloper.muuvi.viewmodel.AddViewModel
import kotlinx.android.synthetic.main.fragment_add.*

class AddFragment : Fragment(),View.OnClickListener {

    private lateinit var vm: AddViewModel

    private val adapter = RecyclerViewMovieAdapter(arrayListOf())

    private lateinit var binding: FragmentAddBinding

    private lateinit var layoutManager: LinearLayoutManager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        vm = activity?.run {
            ViewModelProviders.of(this)[AddViewModel::class.java]
        } ?: throw Exception("Invalid activity")
    }

    override fun onCreateView(
        inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?
    ): View? {
        binding =
            DataBindingUtil.inflate(inflater,R.layout.fragment_add,container,false)
        binding.addViewModel = vm
        return binding.root
    }

    override fun onViewCreated(view: View,savedInstanceState: Bundle?) {
        super.onViewCreated(view,savedInstanceState)
        initUI()
    }

    private fun initUI() {
        setRecyclerView()
        observe()
        setProgress(isRecyclerViewGone = false,isProgressLLViewGone = true)
        binding.isClearIVGone = true
        setListeners()
        fragment_add_movieSeriesET.requestFocus()
        val imm = context?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        imm.showSoftInput(fragment_add_movieSeriesET,InputMethodManager.SHOW_IMPLICIT)
    }

    private fun setRecyclerView() {
        layoutManager = LinearLayoutManager(context)
        fragment_add_mainRV.layoutManager = layoutManager
        fragment_add_mainRV.adapter = adapter
    }

    private fun observe() {
        vm.movieList.observe(viewLifecycleOwner,Observer { movieList ->
            movieList?.let {
                adapter.updateMovieList(it)
            }
        })

        vm.isError.observe(viewLifecycleOwner,Observer { isError ->
            isError?.let {
                setProgress(isRecyclerViewGone = false,isProgressLLViewGone = true)
                if (it) {
                    setToast(resources.getString(R.string.something_went_wrong_please_try_again_later))
                }
            }
        })

        vm.isLoading.observe(viewLifecycleOwner,Observer { isLoading ->
            isLoading?.let {
                if (it) {
                    setProgress(isRecyclerViewGone = true,isProgressLLViewGone = false)
                } else {
                    setProgress(isRecyclerViewGone = false,isProgressLLViewGone = true)

                }
            }
        })

        vm.movieSeriesETContent.observe(viewLifecycleOwner,Observer {
            if (it.isNotEmpty()) {
                vm.refreshData(it,1)
                binding.isClearIVGone = false
            } else {
                adapter.updateMovieList(arrayListOf())
                binding.isClearIVGone = true
            }
        })
    }

    private fun setProgress(isRecyclerViewGone: Boolean,isProgressLLViewGone: Boolean) {
        if (vm.movieSeriesETContent.value != null) {
            val text =
                "${resources.getString(R.string.searching_for)} \"${vm.movieSeriesETContent.value}\"..."
            binding.searchingFor = text
        }

        binding.isMainRVGone = isRecyclerViewGone
        binding.isProgressLLGone = isProgressLLViewGone
    }

    private fun setToast(text: String) {
        Toast.makeText(context,text,Toast.LENGTH_SHORT).show()
    }

    private fun setListeners() {
        fragment_add_clearIV.setOnClickListener(this)
    }

    override fun onClick(v: View?) {
        if (v != null) {
            when (v.id) {
                R.id.fragment_add_clearIV -> fragment_add_movieSeriesET.text.clear()
            }
        }
    }
}

AddViewModel.kt

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.martiandeveloper.muuvi.model.MovieResult
import com.martiandeveloper.muuvi.model.Movie
import com.martiandeveloper.muuvi.service.MovieService
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.observers.DisposableSingleObserver
import io.reactivex.schedulers.Schedulers

class AddViewModel : ViewModel() {

    private val movieService = MovieService()
    private val disposable = CompositeDisposable()

    val movieList = MutableLiveData<ArrayList<Movie>>()
    val isError = MutableLiveData<Boolean>()
    val isLoading = MutableLiveData<Boolean>()
    val movieSeriesETContent = MutableLiveData<String>()

    fun refreshData(movie: String,page: Int) {
        isLoading.value = true
        disposable.add(
            movieService.getData(movie,page).subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeWith(object : DisposableSingleObserver<MovieResult>() {
                    override fun onSuccess(t: MovieResult) {
                        movieList.value = t.results
                        isError.value = false
                        isLoading.value = false
                    }

                    override fun onError(e: Throwable) {
                        isError.value = true
                        isLoading.value = false
                    }

                })
        )
    }
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...