Kotlin recyclerview 分页重启(Pagination)
Posted
技术标签:
【中文标题】Kotlin recyclerview 分页重启(Pagination)【英文标题】:Kotlin recyclerview pagination restarts (Pagination) 【发布时间】:2022-01-15 09:49:35 【问题描述】:我目前正在开发一个基于 TMDB 的 Kotlin 应用程序,试图实现分页我实现了它,但是当添加更多项目时,recyclerview “重新启动”(将我发送到列表顶部)。
我认为问题可能是我的适配器或我设置 recylerview 的方式。
有什么建议吗?
我的适配器
class SearchMovieAdapter(val movieList: ArrayList<MovieData>, val listener: ClickListener) :
RecyclerView.Adapter<SearchMovieAdapter.SearchViewHolder>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SearchViewHolder
val view: LayoutInflater = LayoutInflater.from(parent.context)
return SearchViewHolder(view.inflate(R.layout.search_item, parent, false))
override fun onBindViewHolder(holder: SearchViewHolder, position: Int)
return holder.bindInfo(movieList[position])
override fun getItemCount(): Int
return movieList.size
inner class SearchViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
var itemImage: ImageView = itemView.findViewById(R.id.imageFound)
fun bindInfo(movie: MovieData)
itemView.setOnClickListener
//listener.OnItemClick(movie.id.toString(), image.context)
listener.OnItemClick(movie, itemImage.context)
// title.text = movie.title
if (movie.poster_path != null)
Picasso.get().load("https://image.tmdb.org/t/p/w500$movie.poster_path")
.into(itemImage)
实施
class SearchPage :
ClickListener,
AppCompatActivity()
private lateinit var editableText: EditText
private lateinit var listOfSearchedMovies: RecyclerView
var searchedQuery: ArrayList<MovieData> = ArrayList()
var queryText: String = ""
var indexPage = 1
val indexLimit = 3
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_search_page)
editableText = findViewById(R.id.buscarPeli)
//When user click enter key on keyboard
editableText.setOnKeyListener(View.OnKeyListener _, keyCode, event ->
if (keyCode == KeyEvent.KEYCODE_ENTER && event.action == KeyEvent.ACTION_DOWN)
//Perform Code
val query: String = editableText.text.toString()
queryText = query
//Search movies data
if (searchedQuery.isEmpty())
setSearchedTitle(query, indexPage.toString())
editableText.text.clear()
hideKeyboard()
Toast.makeText(this, query, Toast.LENGTH_SHORT).show()
return@OnKeyListener true
false
)
private fun hideKeyboard()
val view = this.currentFocus
if (view != null)
val hide = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
hide.hideSoftInputFromWindow(view.windowToken, 0)
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)
private fun setSearchedTitle(query: String, index: String)
val retrofitBuilder = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(com.example.recyclerview.BASE_URL)
.build()
.create(API_interface::class.java)
val retrofitData = retrofitBuilder.searchMovies(query, index)
retrofitData.enqueue(object : Callback<MoviesResponse?>
override fun onResponse(
call: Call<MoviesResponse?>,
response: Response<MoviesResponse?>
)
if (response.isSuccessful)
//searchedQuery.clear()
val totalResults = response.body()!!.results.size
for (i in 0 until totalResults)
searchedQuery.add(response.body()!!.results[i])
//Log.d("Respuesta", "Lista respuesta $searchedQuery.size ")
//index=index+1
setMoviesRecyclerView(searchedQuery)
override fun onFailure(call: Call<MoviesResponse?>, t: Throwable)
Toast.makeText(this@SearchPage, "$t.message", Toast.LENGTH_SHORT).show()
)
private fun setMoviesRecyclerView(searchedQuery: ArrayList<MovieData>)
val loading: ProgressBar = findViewById(R.id.movieResultsLoading)
listOfSearchedMovies = findViewById(R.id.searcheMovies)
listOfSearchedMovies.apply
val layoutManager: RecyclerView.LayoutManager =
GridLayoutManager(listOfSearchedMovies.context, 2)
listOfSearchedMovies.layoutManager = layoutManager
adapter = SearchMovieAdapter(searchedQuery, this@SearchPage)
listOfSearchedMovies.addOnScrollListener(object : RecyclerView.OnScrollListener()
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int)
super.onScrolled(recyclerView, dx, dy)
if (!recyclerView.canScrollVertically(1))
indexPage++
if (indexPage > indexLimit)
Toast.makeText(
recyclerView.context,
"¡That's all!",
Toast.LENGTH_LONG
).show()
else
setSearchedTitle(queryText, indexPage.toString())
)
我尝试添加另一种方法来仅将项目添加到列表中,但这样做视图不会刷新
【问题讨论】:
你需要实现NotifyDataChanged:For better explanation 我尝试了你的建议,但是,recyclerview 更新的唯一方法是向上滚动 【参考方案1】:问题是您每次收到一些新数据时都在初始化适配器。
尝试在 SearchMovieAdapter
类中添加 insertMovie
函数,该函数添加单个项目并通知其插入:
fun insertMovie(newMovie: MovieData)
this.movieList.add(newMovie)
notifyItemInserted(movieList.size - 1)
然后在每次收到新对象时使用它来更新您的适配器:
retrofitData.enqueue(object : Callback<MoviesResponse?>
override fun onResponse(
call: Call<MoviesResponse?>,
response: Response<MoviesResponse?>
)
if (response.isSuccessful)
//searchedQuery.clear()
val totalResults = response.body()!!.results.size
for (i in 0 until totalResults)
adapter.insertMovie(response.body()!!.results[i])
【讨论】:
不只是重新创建适配器,还分配一个新的LayoutManager
- 你基本上每次都清除整个RecyclerView
,这就是它重置的原因以上是关于Kotlin recyclerview 分页重启(Pagination)的主要内容,如果未能解决你的问题,请参考以下文章
提供Kotlin阵列的补偿 .take(n:Int)。这是分页的好方法吗?
Kotlin、RecyclerView、ViewBinding