RecyclerView适配器onItemClick事件未触发



我是一名Java Android开发人员,正在尝试重新学习Kotlin中的RecyclerView适配器。

我有一个碎片,里面有一个RecyclerView。我在Fragment类中初始化了适配器和OnItemClickListener。然而,我的onItemClick((从未被触发。日志.d从不显示。

突破性新闻片段.kt

class BreakingNewsFragment : Fragment(R.layout.fragment_breaking_news) {
lateinit var viewModel: NewsViewModel
lateinit var newsAdapter: NewsAdapter
val TAG = "BreakingNewsFragment"
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = (activity as NewsActivity).viewModel
setupRecyclerView()
Log.d(TAG, "onitemclick") // this shows!
newsAdapter.setOnItemClickListener {
Log.d(TAG, "onitemclick") // this won't show
val bundle = Bundle().apply {
putSerializable("article", it)
}
findNavController().navigate(
R.id.action_breakingNewsFragment_to_articleFragment,
bundle
)
}
viewModel.breakingNews.observe(viewLifecycleOwner, Observer { response ->
when(response) {
is Resource.Success -> {
hideProgressBar()
response.data?.let { newsResponse ->
newsAdapter.differ.submitList(newsResponse.articles)
}
}
is Resource.Error -> {
hideProgressBar()
response.message?.let {message ->
Log.e(TAG, "An error occurred: $message")
}
}
is Resource.Loading -> {
showProgressBar()
}
}
})
}
private fun hideProgressBar() {
paginationProgressBar.visibility = View.INVISIBLE
}
private fun showProgressBar() {
paginationProgressBar.visibility = View.VISIBLE
}
private fun setupRecyclerView() {
newsAdapter = NewsAdapter()
rvBreakingNews.apply {
adapter = newsAdapter
layoutManager = LinearLayoutManager(activity)
}
}
}

NewsAdapter.kt

class NewsAdapter : RecyclerView.Adapter<NewsAdapter.ArticleViewHolder>() {
inner class ArticleViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)
private val differCallback = object : DiffUtil.ItemCallback<Article>() {
override fun areItemsTheSame(oldItem: Article, newItem: Article): Boolean {
// can't compare article IDs; articles from API do not have IDs. but URLs are unique for each article so we can compare those
return oldItem.url == newItem.url
}
override fun areContentsTheSame(oldItem: Article, newItem: Article): Boolean {
return oldItem == newItem
}
}
// instead of using a standard list to store objects, use this ListDiffer to calculate differences between lists
val differ = AsyncListDiffer(this, differCallback)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ArticleViewHolder {
return ArticleViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.item_article_preview, parent,false)
)
}
override fun getItemCount(): Int {
return differ.currentList.size
}
override fun onBindViewHolder(holder: ArticleViewHolder, position: Int) {
val article = differ.currentList[position]
holder.itemView.apply { // apply: reference views directly
Glide.with(this).load(article.urlToImage).into(ivArticleImage)
tvSource.text = article.source.name
tvTitle.text = article.title
tvDescription.text = article.description
tvPublishedAt.text = article.publishedAt
setOnItemClickListener { onItemClickListener?.let( { it(article) }) }
}
}
private var onItemClickListener: ((Article) -> Unit)? = null // pass current article to function, open webview page from there
fun setOnItemClickListener(listener: (Article) -> Unit) {
onItemClickListener = listener
}
}

holder.itemView.apply {中,您没有将回调分配给holder.itemView;您正在调用setOnItemClickListener,它所做的只是更改onItemClickListener,它实际上是一个局部变量,而不是视图中的回调函数。

你想做的是:


holder.itemView.apply { // apply: reference views directly
..
setOnClickListener { onItemClickListener?.let( { it(article) }) }
}

(注意,这是setOnClickListener,而不是setOn*Item*ClickListener(

我建议您将var onItemClickListener设为非私有,直接从适配器外部使用,然后删除fun setOnItemClickListener()。。。在Kotlin世界中,像这样的公共var被编译为具有它们的setter,所以您不再真正需要Java样式的setter了。

最新更新