Kotlin: Как передать данные из recyclerview во фрагменте в другой фрагмент с помощью модели просмотра / интерфейса? - PullRequest
0 голосов
/ 21 июня 2020

Мне не удалось найти пример передачи данных из адаптера recyclerview во фрагмент с использованием viewmodel или интерфейса в kotlin. Я пытался использовать только пакет, но в принимающем фрагменте я получил нулевой пакет. Вот мой адаптер Recyclerview фрагмент кода.

class QnAMyProfileEditRecyclerViewAdapter(private val context: Context) : RecyclerView.Adapter<QnAMyProfileEditRecyclerViewAdapter.Holder>() {


    private var currentUserQnADataMyProfileEdit = emptyList<QnAData>()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {

        val view: View = if (viewType == R.layout.rv_item_qn_a_my_profile) {

            LayoutInflater.from(parent.context)
                .inflate(R.layout.rv_item_qn_a_my_profile, parent, false)

        } else {

            LayoutInflater.from(parent.context)
                .inflate(R.layout.rv_footer_new_qna_my_profile, parent, false)

        }
        return Holder(view)
    }

    override fun getItemCount(): Int {
        return currentUserQnADataMyProfileEdit.size + 1
    }

    //implement Floating Action Button at the bottom of the recyclerview
    override fun getItemViewType(position: Int): Int {

        return if (position == currentUserQnADataMyProfileEdit.size) {
            R.layout.rv_footer_new_qna_my_profile
        } else {
            R.layout.rv_item_qn_a_my_profile
        }
    }

    override fun onBindViewHolder(holder: Holder, position: Int) {

        if (position == currentUserQnADataMyProfileEdit.size) {
            holder.viewHolderNewQnA?.setOnClickListener {
                Toast.makeText(context, "New item intent", Toast.LENGTH_SHORT).show()
            }
        } else {
            //Normal bind for RecyclerView
            holder.bindData(currentUserQnADataMyProfileEdit[position])
            holder.viewHolderCRUDQnAMyProfile?.setOnClickListener {


                //Give QnACrud current QnAData --- send bundle
                val bundle = Bundle()
                bundle.putString(
                    "currentQnAQuestion",
                    currentUserQnADataMyProfileEdit[position].question
                )
                bundle.putString(
                    "currentQnAAnswer",
                    currentUserQnADataMyProfileEdit[position].answer
                )
                QnAMyProfileEditCRUDFragment().arguments = bundle
                val activity: AppCompatActivity = context as AppCompatActivity
                activity.supportFragmentManager.beginTransaction()
                    .add(R.id.cl_my_profile_edit, QnAMyProfileEditCRUDFragment())
                    .addToBackStack(null).commit()




            }
        }
    }


    fun setData(updateList: List<QnAData>) {
        this.currentUserQnADataMyProfileEdit = updateList
        notifyDataSetChanged()
    }

    inner class Holder(itemView: View) : RecyclerView.ViewHolder(itemView) {




        val viewHolderQuestion =
            itemView.findViewById(R.id.txt_question_qna_my_profile_edit) as TextView?
        val viewHolderAnswer =
            itemView.findViewById(R.id.txt_answer_qna_my_profile_edit) as TextView?

        val viewHolderNewQnA =
            itemView.findViewById(R.id.fab_new_qna_my_profile_edit) as FloatingActionButton?

        val viewHolderCRUDQnAMyProfile =
            itemView.findViewById(R.id.fab_crud_qna_my_profile_edit) as FloatingActionButton?


        //Bind data with inflaters
        fun bindData(currentUserInList: QnAData) {

            viewHolderQuestion?.text = currentUserInList.question
            viewHolderAnswer?.text = currentUserInList.answer
        }

    }
}

Вот мой фрагмент , который, как предполагается, получит данные (bundle):

class QnAMyProfileEditCRUDFragment : Fragment() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        //Get bundle data and set Edit Text values


        val bundle:Bundle? = arguments //Bundle == null!!!!
        val qnaQuestionData: String? = bundle?.getString("currentQnAQuestion")
        val qnaAnswerData: String? = bundle?.getString("currentQnAAnswer")
        et_qna_question.setText(qnaQuestionData)
        et_qna_answer.setText(qnaAnswerData)


    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {



        return inflater.inflate(R.layout.fragment_qn_a_my_profile_edit_c_r_u_d, container, false)
    }

    override fun onAttach(context: Context) {
        super.onAttach(context)


    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        //Pop fragment if grey area(outside the box) is tapped
        imv_overlay.setOnClickListener {
            fragmentManager?.popBackStack()
        }
    }

}

QnAData - это простой data class с двумя членами question и answer, оба являются string type

Ответы [ 3 ]

1 голос
/ 21 июня 2020

Во-первых, нужно сделать несколько рефакторов в вашем коде:

  1. внутренний класс может привести к утечке памяти, поэтому измените ViewHolder на:
  2. Поместите слушателя кликов в свой ViewHolder

ViewHolder

class MyViewHolder(...) : RecyclerView.ViewHolder(...) {

    fun bind(model: Model) {
        ...

        itemView.setOnClickListener {
            callback?.onSomeEventHappened(model)
            //you can also pass lambda here instead of using an interface for callback
        }

    }

}
RecyclerViewAdapter должен определить протокол для связи с фрагментом:
class Adapter : RecyclerView.Adapter<T>() {

    interface callback {
        fun onSomeEventHappened()
    }


    private var callback: callback? = null

    
    fun setListener(listener: Callback) {
        callback = listener
    }

}
Если данные разделяются между двумя фрагментами, используйте SharedViewModel Если вам нужно передать данные, вы можете сделать это либо аргументами AndroidNavigationCompoent, либо передать их при создании фрагмента:
val SomeFragment = SomeFragment().apply {
    SomeFragment.arguments = ... //A bundle for example
}
1 голос
/ 21 июня 2020

Предполагая, что у вас есть viewModel, совместно используемый для вашей активности контейнера Fragment и дочерних фрагментов, вы можете передать ту же самую viewModel своему адаптеру recyclerview. данные из Activity или Fragment.

1 голос
/ 21 июня 2020

Попробуйте создать конструктор внутри вашего фрагмента, затем beginTransaction

val fragment = QnAMyProfileEditCRUDFragment.newInstance( 
currentUserQnADataMyProfileEdit[position].question, 
currentUserQnADataMyProfileEdit[position].answer)

activity.supportFragmentManager.beginTransaction()
                    .add(R.id.cl_my_profile_edit,fragment)
                    .addToBackStack(null).commit()

Внутри QnAMyProfileEditCRUDFragment вы можете просто использовать значения из конструктора

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...