我有两个片段:(1)图书馆片段,(2)书片段
图书馆碎片通过RecyclerView显示所有可用的书籍。用户可以在每个RecyclerView项目上设置标签,这将把LiveData设置为相应的图书。同时,书籍片段将被打开,并显示该书的内容。
我在ViewHolder类中设置了一个onClickListener,它位于图书馆片段的RecyclerView. Adapter中。因此,当单击一个项目时,livedata将被设置,然后通过导航组件导航到图书片段。图书片段在实时数据上有一个观察者并显示它。
正如您在下面的代码中所看到的,我正在将viewmodel实例传递给适配器,这是不正确的。。。。?还是这样?这应该怎么做?
库片段代码片段
class LibraryFragment : Fragment() {
[...]
private val model: SharedViewModel by activityViewModels()
private lateinit var gridlayoutManager: GridLayoutManager
private lateinit var thumbnailAdapter: ThumbnailAdapter
private lateinit var thumbnailRecyclerView: RecyclerView
private lateinit var selectedFolder: Uri
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = layoutInflater.inflate(R.layout.fragment_thumbnail_viewer, container, false)
initRecyclerView(view)
view.allFolderPicker.setOnClickListener {
pickFolder()
}
view.switchFragment.setOnClickListener {
findNavController().navigate(R.id.action_allFoldersFragment_to_oneFolderFragment)
}
return view
}
private fun initRecyclerView(view: View) {
thumbnailRecyclerView = view.findViewById(R.id.thumbnail_recycler_view)
gridlayoutManager =
GridLayoutManager(requireContext(), 3, LinearLayoutManager.VERTICAL, false)
thumbnailRecyclerView.layoutManager = gridlayoutManager
thumbnailAdapter = ThumbnailAdapter(model)
thumbnailAdapter.setThumbnailList(listOf())
thumbnailRecyclerView.adapter = thumbnailAdapter
}
[...]
}
适配器类代码片段
class ThumbnailAdapter(model: SharedViewModel) :
RecyclerView.Adapter<ThumbnailAdapter.CustomViewHolder>() {
private var thumbnailList = listOf<Pair<String, File>>()
private val myModel = model
inner class CustomViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private val thumbnail = view.thumbnail
private val title = view.title
fun bind(item: Pair<String, File>) {
val titleToSet = item.first
val bitmapToSet = Util.uriToBitmap(item.second)
val resizedBitmapToSet = Bitmap.createScaledBitmap(bitmapToSet, 150, 150, false)
thumbnail.setImageBitmap(resizedBitmapToSet)
title.text = titleToSet
itemView.setOnClickListener {
val folderWithImages = thumbnailList[adapterPosition].second.parentFile
folderWithImages?.let {
myModel.setLibraryFolderList(it)
itemView.findNavController()
.navigate(R.id.action_allFoldersFragment_to_oneFolderFragment)
}
}
}
}
[...]
}
书本片段代码片段
[...]
class BookViewFragment : Fragment() {
private lateinit var viewPager: ViewPager2
private lateinit var viewPagerAdapter: ViewPager2Adapter
private val model: SharedViewModel by activityViewModels()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_image_viewer, container, false)
initRecyclerView(view)
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
model.selectedBookFile.observe(viewLifecycleOwner, androidx.lifecycle.Observer {
viewPagerAdapter.setImageList(getImageList(it))
viewPagerAdapter.notifyDataSetChanged()
})
}
private fun initRecyclerView(view: View) {
viewPager = view.findViewById(R.id.main_image)
viewPagerAdapter = ViewPager2Adapter()
viewPagerAdapter.setImageList(listOf())
viewPager.adapter = viewPagerAdapter
}
[...]
}
我知道现在回答太晚了。但我希望它能帮助其他开发者寻找类似问题的解决方案。
看看LiveAdapter。
您只需要在Gradle中添加最新的依赖项。
dependencies {
implementation 'com.github.RaviKoradiya:LiveAdapter:1.3.4'
// kapt 'com.android.databinding:compiler:GRADLE_PLUGIN_VERSION' // this line only for Kotlin projects
}
并将适配器与RecyclerView绑定
// Kotlin sample
LiveAdapter(
data = liveListOfItems,
lifecycleOwner = this@MainActivity,
variable = BR.item )
.map<Header, ItemHeaderBinding>(R.layout.item_header) {
onBind{
}
onClick{
}
areContentsTheSame { old: Header, new: Header ->
return@areContentsTheSame old.text == new.text
}
areItemSame { old: Header, new: Header ->
return@areContentsTheSame old.text == new.text
}
}
.map<Point, ItemPointBinding>(R.layout.item_point) {
onBind{
}
onClick{
}
areContentsTheSame { old: Point, new: Point ->
return@areContentsTheSame old.id == new.id
}
areItemSame { old: Header, new: Header ->
return@areContentsTheSame old.text == new.text
}
}
.into(recyclerview)
就这样。不需要为适配器实现编写额外的代码,观察LiveData并通知适配器。
此外,有DiffUtil实现,所以只有更改的项目将更新RecyclerView,而不是所有。
简单地在Adapter类中使用您的活动
引用,而不是viewLiefycleOwner
,它就会工作
class ThumbnailAdapter(
private val activity: FragmentActivity
) : RecyclerView.Adapter<ThumbnailAdapter.CustomViewHolder>() {
// ... Other functions
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
model.selectedBookFile.observe(activity, androidx.lifecycle.Observer {
// Your code goes here
})
}
// ... Other functions
}
你不应该这样做,这里有一个关于RecyclerView的课程,从显示到处理clickListener。
以下是他们对它的定义:
虽然ViewHolder
是一个聆听点击的好地方,但它通常不是处理点击的正确地方。通常应该在ViewModel
中处理点击,因为ViewModel
可以访问数据和逻辑,以确定点击后需要发生什么。
所以你应该这样做:
适配器:
class ThumbnailAdapter(model: SharedViewModel, val clickListener: ThumbnailListener) :
RecyclerView.Adapter<ThumbnailAdapter.CustomViewHolder>() {
private var thumbnailList = listOf<Pair<String, File>>()
private val myModel = model
override fun onBindViewHolder(holder: CustomViewHolder, position: Int) {
val item = getItem(position)
holder.itemView.setOnClickListener {
listener.onClick(item)
}
holder.bind(marsProperty)
}
inner class CustomViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private val thumbnail = view.thumbnail
private val title = view.title
fun bind(item: Pair<String, File>) {
val titleToSet = item.first
val bitmapToSet = Util.uriToBitmap(item.second)
val resizedBitmapToSet = Bitmap.createScaledBitmap(bitmapToSet, 150, 150, false)
thumbnail.setImageBitmap(resizedBitmapToSet)
title.text = titleToSet
}
}
class ThumbnailListener(val clickListener: (libraryId: Long) -> Unit) {
fun onClick(val library: Library) = clickListener(library.id)
}
[...]
}
视图模型:
private val _navigateToBook = MutableLiveData<Long>()
val navigateToBook: LiveData<Long>()
get() = _navigateToBook
fun onLibraryClicked(libraryId: Long) {
// your stuff
_navigateToBook.value = libraryId
}
片段:
thumbnailAdapter = ThumbnailAdapter(model, ThumbnailListener { libraryId ->
viewModel.onLibraryClicked(libraryId)
})
viewModel.navigateToBook.observe(viewLifecycleOwner, Observer { book ->
book?.let {
this.findNavController().navigate(YOUR_DESTINATION)
}
})
XML项目文件:
<data>
<variable
name="listener"
type="Your.Package.To.ThumbnailListener" />
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="170dp"
android:onClick="@{() -> listener.onClick(property)}">
...
</FrameLayout>
适配器:
fun bind(item: Pair<String, File>, listener: ThumbnailListener) {
val titleToSet = item.first
val bitmapToSet = Util.uriToBitmap(item.second)
val resizedBitmapToSet = Bitmap.createScaledBitmap(bitmapToSet, 150, 150, false)
thumbnail.setImageBitmap(resizedBitmapToSet)
title.text = titleToSet
itemView.clickListener = listener
}
我已经尝试解决一个问题几个小时了,但我没有解决它。我尝试为可扩展列表视图设置适配器,但我接受了这个错误。多谢了。“尝试对空对象引用调用虚拟方法”void Android.Widget.ExpandableListView.SetAdapter(Android.Widget.ExpandableListAdapter)“”
我注释了setIntTag(String),但Jaxb marchaller调用setIntTag(Integer)并将Integer传递给它,如果我删除setIntTag(Integer),marchaller调用字符串setter。 如何注释这些方法以保留两个setter,并告诉编组程序使用字符串setter?
首先我在使用 keycloak-authz-client-3.3.0.final Spring boot 1.5.8.发布 spring-boot-starter-security 我一直在玩Keycloak spring adapter,探索示例,因为我们想在我们的项目中采用它。 我可以使用以下教程轻松地让它在角色中运行:https://dzone.com/articles/elyly-secu
我正在尝试制作的音乐播放器中使用Volley。 下面是我如何定义音乐播放器中的歌曲。我有一个带有一些属性的“歌曲对象” 我使用albumArtURI用图像填充各种列表和网格视图。 要获取专辑ArtURI,我对其进行查询。如果URI不存在,我必须从Internet上拉取一个图像URL。 所以我设置了截取,从iTunes中提取JSON对象,解析对象,并获取它们的图像URL。 例如,这里是iTunesJ
我为后台服务实现了一个AsyncTask来执行对数据库的查询,该查询速度非常快,不超过2-3秒。AsyncTask中的ProgressDialog有时很难检测到。 我的问题是,当任务完成并且我检索到游标时,当我将适配器设置到RecyclerView时,流程会冻结我的UI几秒钟,直到数据设置完毕。当我执行搜索(新查询,与获取所有行相同的过程,但行数较少),并替换光标以更新数据时,也会发生这种情况。
我是kotlin android的新手。我已经创建了回收站视图的适配器。但是我不能为每个回收站视图项目执行单击事件。我需要参考代码的解释。请帮我做这件事。提前谢谢。这是我的代码供您参考。