Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何在两个片段和ListViewAdapter(RecyclerView)之间共享数据_Android_Kotlin_Android Fragments_Android Recyclerview_Android Livedata - Fatal编程技术网

Android 如何在两个片段和ListViewAdapter(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

我需要将数据从ListAdapter(recyclerView中单击的项)传递到第二个片段。我尝试了这个(下面的代码),但没有成功。我是新手,但我真的不明白。谢谢你的回答

我有这个视图模型:

    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检查更新的答案