Android 如何在两个片段和ListViewAdapter(RecyclerView)之间共享数据
我需要将数据从ListAdapter(recyclerView中单击的项)传递到第二个片段。我尝试了这个(下面的代码),但没有成功。我是新手,但我真的不明白。谢谢你的回答 我有这个视图模型:Android 如何在两个片段和ListViewAdapter(RecyclerView)之间共享数据,android,kotlin,android-fragments,android-recyclerview,android-livedata,Android,Kotlin,Android Fragments,Android Recyclerview,Android Livedata,我需要将数据从ListAdapter(recyclerView中单击的项)传递到第二个片段。我尝试了这个(下面的代码),但没有成功。我是新手,但我真的不明白。谢谢你的回答 我有这个视图模型: class ContactItemViewModel: ViewModel() { private val mutableContactItem = MutableLiveData<Contact>() val selectedItem: LiveData<Con
class ContactItemViewModel: ViewModel() {
private val mutableContactItem = MutableLiveData<Contact>()
val selectedItem: LiveData<Contact> get() = mutableContactItem
fun selectContactItem(_item: Contact){
mutableContactItem.value = _item
}
}
class DetailsFragment() : Fragment() {
private lateinit var detailsFragmentBinding: FragmentDetailsBinding
private lateinit var contactItem: Contact
private val contactItemViewModel: ContactItemViewModel by activityViewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
detailsFragmentBinding = FragmentDetailsBinding.inflate(layoutInflater)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val contactItemViewModel = ViewModelProvider(requireActivity()).get(ContactItemViewModel::class.java)
contactItemViewModel.selectedItem.observe(viewLifecycleOwner, Observer {
setDetailedInfo(it)
})
return inflater.inflate(R.layout.fragment_details, container, false)
}
private fun setDetailedInfo(item: Contact){
val transformation = CircleTransformation()
detailsFragmentBinding.tvName.text = item.name
detailsFragmentBinding.tvEmail.text = item.email
Picasso.get()
.load(item.getGravatarUri())
.fit().centerCrop()
.placeholder(R.mipmap.ic_contact)
.transform(transformation)
.into(detailsFragmentBinding.ivAvatar)
}
/*companion object {
@JvmStatic
fun newInstance() = DetailsFragment(_item =)
}*/
}
class ListItemAdapter(
private val context: Context,
private val dataset: List<Contact>,
private var contactItemViewModel: ContactItemViewModel
) : RecyclerView.Adapter<ListItemAdapter.ItemViewHolder>() {
class ItemViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
val tvName: TextView = view.findViewById(R.id.tv_name)
val ivAvatar: ImageView = view.findViewById(R.id.iv_avatar)
}
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
super.onAttachedToRecyclerView(recyclerView)
if(contactItemViewModel == null){
contactItemViewModel = ViewModelProvider((recyclerView.context as ViewModelStoreOwner)!!).get(
ContactItemViewModel::class.java
)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
val adapterLayout = LayoutInflater.from(parent.context).inflate(
R.layout.list_item, parent, false
)
return ItemViewHolder(adapterLayout)
}
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
val item = dataset[position]
val transformation = CircleTransformation()
holder.tvName.text = item.name
Picasso.get()
.load(item.getGravatarUri())
.fit().centerCrop()
.placeholder(R.mipmap.ic_contact)
.transform(transformation)
.into(holder.ivAvatar)
holder.itemView.setOnClickListener { v ->
val activity = v!!.context as AppCompatActivity
val bundle: Bundle = Bundle()
contactItemViewModel.selectContactItem(item)
val detailsFragment = DetailsFragment()
activity.supportFragmentManager.beginTransaction()
.replace(R.id.fl_content, detailsFragment)
.addToBackStack("detailsFragmentBackStack").commit()
}
}
override fun getItemCount(): Int = dataset.size
}
class ContactsActivity : AppCompatActivity() {
private lateinit var contactsActivityBinding :ActivityContactsBinding
private val contactItemViewModel: ContactItemViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
contactsActivityBinding = ActivityContactsBinding.inflate(layoutInflater)
setContentView(contactsActivityBinding.root)
if (savedInstanceState == null) {
val manager = supportFragmentManager
val transaction = manager.beginTransaction()
transaction.replace(contactsActivityBinding.flContent.id, PeopleFragment.newInstance())
transaction.commit()
}
}
}
和此适配器:
class ContactItemViewModel: ViewModel() {
private val mutableContactItem = MutableLiveData<Contact>()
val selectedItem: LiveData<Contact> get() = mutableContactItem
fun selectContactItem(_item: Contact){
mutableContactItem.value = _item
}
}
class DetailsFragment() : Fragment() {
private lateinit var detailsFragmentBinding: FragmentDetailsBinding
private lateinit var contactItem: Contact
private val contactItemViewModel: ContactItemViewModel by activityViewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
detailsFragmentBinding = FragmentDetailsBinding.inflate(layoutInflater)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val contactItemViewModel = ViewModelProvider(requireActivity()).get(ContactItemViewModel::class.java)
contactItemViewModel.selectedItem.observe(viewLifecycleOwner, Observer {
setDetailedInfo(it)
})
return inflater.inflate(R.layout.fragment_details, container, false)
}
private fun setDetailedInfo(item: Contact){
val transformation = CircleTransformation()
detailsFragmentBinding.tvName.text = item.name
detailsFragmentBinding.tvEmail.text = item.email
Picasso.get()
.load(item.getGravatarUri())
.fit().centerCrop()
.placeholder(R.mipmap.ic_contact)
.transform(transformation)
.into(detailsFragmentBinding.ivAvatar)
}
/*companion object {
@JvmStatic
fun newInstance() = DetailsFragment(_item =)
}*/
}
class ListItemAdapter(
private val context: Context,
private val dataset: List<Contact>,
private var contactItemViewModel: ContactItemViewModel
) : RecyclerView.Adapter<ListItemAdapter.ItemViewHolder>() {
class ItemViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
val tvName: TextView = view.findViewById(R.id.tv_name)
val ivAvatar: ImageView = view.findViewById(R.id.iv_avatar)
}
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
super.onAttachedToRecyclerView(recyclerView)
if(contactItemViewModel == null){
contactItemViewModel = ViewModelProvider((recyclerView.context as ViewModelStoreOwner)!!).get(
ContactItemViewModel::class.java
)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
val adapterLayout = LayoutInflater.from(parent.context).inflate(
R.layout.list_item, parent, false
)
return ItemViewHolder(adapterLayout)
}
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
val item = dataset[position]
val transformation = CircleTransformation()
holder.tvName.text = item.name
Picasso.get()
.load(item.getGravatarUri())
.fit().centerCrop()
.placeholder(R.mipmap.ic_contact)
.transform(transformation)
.into(holder.ivAvatar)
holder.itemView.setOnClickListener { v ->
val activity = v!!.context as AppCompatActivity
val bundle: Bundle = Bundle()
contactItemViewModel.selectContactItem(item)
val detailsFragment = DetailsFragment()
activity.supportFragmentManager.beginTransaction()
.replace(R.id.fl_content, detailsFragment)
.addToBackStack("detailsFragmentBackStack").commit()
}
}
override fun getItemCount(): Int = dataset.size
}
class ContactsActivity : AppCompatActivity() {
private lateinit var contactsActivityBinding :ActivityContactsBinding
private val contactItemViewModel: ContactItemViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
contactsActivityBinding = ActivityContactsBinding.inflate(layoutInflater)
setContentView(contactsActivityBinding.root)
if (savedInstanceState == null) {
val manager = supportFragmentManager
val transaction = manager.beginTransaction()
transaction.replace(contactsActivityBinding.flContent.id, PeopleFragment.newInstance())
transaction.commit()
}
}
}
我觉得问题出在这段代码中:
holder.itemView.setOnClickListener { v ->
val activity = v!!.context as AppCompatActivity
val bundle: Bundle = Bundle()
contactItemViewModel.selectContactItem(item)
//You are creating the fragment here so old viewmodel instance will be destroyed as new viewModel instance will get created.
//What is the use of below code?
// val detailsFragment = DetailsFragment()
//activity.supportFragmentManager.beginTransaction()
// .replace(R.id.fl_content, detailsFragment)
//.addToBackStack("detailsFragmentBackStack").commit()
//By commenting above line your viewModel function should be called and data should be passed
}
如果要创建新Fragement,请在Fragment类中执行,如下所示:
fun selectContactItem(_item: Contact){
mutableContactItem.value = _item
//observe another mutable live data and then do creation of new fragment
}
这将解决您的数据无法传递的问题我使用此代码创建一个新片段,并将其放置在Activity@DmytroHurskyi检查更新的答案