Je n'ai pas pu trouver d'exemple de transmission de données d'un adaptateur recyclerview à un fragment à l'aide d'un viewmodel ou d'une interface dans kotlin .
J'ai essayé d'utiliser juste un bundle, mais je reçois un bundle nul dans le fragment de réception.
Voici mon extrait de code Recyclerview Adapter .
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()
}
}
}
Voici mon fragment qui est supposé recevoir les données ( bundle ):
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
}
}
}
QnAData est une simple classe de données avec deux membres question code > et answer sont tous deux du type de chaîne
3 Réponses :
Essayez de créer un constructeur dans votre fragment, puis 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()
Dans le QnAMyProfileEditCRUDFragment, vous pouvez simplement utiliser les valeurs du constructeur
Tout d'abord, il y a quelques refactors à faire sur votre code:
val SomeFragment = SomeFragment().apply {
SomeFragment.arguments = ... //A bundle for example
}
class Adapter : RecyclerView.Adapter<T>() {
interface callback {
fun onSomeEventHappened()
}
private var callback: callback? = null
fun setListener(listener: Callback) {
callback = listener
}
}
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
}
}
}
wow merci beaucoup pour la réponse ... quel est le modèle: paramètre de modèle dans la fonction de liaison?
Le modèle @Ian contient les données que vous utilisez pour travailler avec RecyclerView. val model = User (1, "name") Modifiez également votre onCreateHolder () pour utiliser un type de vue plutôt qu'une condition.
En supposant que viewModel est partagé par pour votre activité de conteneur Fragment et les fragments enfants, vous pouvez transmettre ce même viewModel à votre adaptateur recyclerview.
class Activity: AppCompatActivity {
private val viewModel: AnyViewModel by lazy {
//Initialization
}
private val adapter = Adapter(viewModel)
...
}
class Adapter(viewModel: SomeViewModel) : RecyclerView.Adapter<T>() {
...
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.onBind(anyList[position])
}
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
...
fun onBind(data: SomeData) {
btnSomeAction.setOnClickListener {
//Here change respected data in viewModel or call some method
//viewModel.anyObject = some_value
//viewModel.anyMethodCall()
}
}
}
}
Vous pouvez maintenant accéder à viewModel dans votre adaptateur et utiliser il met à jour les données de l'activité ou du fragment.
Fournissez des parties importantes de votre code pour l'adaptateur RecyclerView.
J'envoie le bundle sur onBindViewHolder dans mon adaptateur