简体   繁体   中英

kotlin: how to pass a data between two fragments

I have simple app that have one Activity , RecyclerView adapter , RecyclerView fragment , and other fragment to display the data of that item i click in RecyclerView but my problem is I don't know how to pass the data of array row with the click fun to show after the new fragment displayed

MainActivity.kt

class MainActivity : AppCompatActivity(),ContentAdapter.ContentListener{
override fun onItemClicked(item: MainMarketTickClass) {
        var ft1 : FragmentTransaction = supportFragmentManager.beginTransaction()
        ft1.replace(R.id.MainFrame,AddCar.newInstanceaddcar())
        ft1.commit()}
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    setContentView(R.layout.activity_main)
    var bnv = findViewById(R.id.navigation) as BottomNavigationView
    bnv.setOnNavigationItemSelectedListener (object : BottomNavigationView.OnNavigationItemSelectedListener{
        override fun onNavigationItemSelected(item: MenuItem): Boolean {
            var selectFragment : Fragment? = null
            when (item.itemId) {
                R.id.navigation_home -> {
                    selectFragment = MainMarket.newInstance()
                }
                R.id.navigation_dashboard -> {
                   selectFragment = AddCar.newInstanceaddcar()
                }
                R.id.navigation_notifications -> {

                }
            }
            var ft : FragmentTransaction = supportFragmentManager.beginTransaction()
            ft.replace(R.id.MainFrame,selectFragment)
            ft.commit()
            return true
        }
    })

    var ft : FragmentTransaction = supportFragmentManager.beginTransaction()
    ft.replace(R.id.MainFrame,MainMarket.newInstance())
    ft.commit()
}

}

ContentAdapter.kt

class ContentAdapter constructor(private val activity: MainActivity, private var listOfData: ArrayList<MainMarketTickClass>, val listener: ContentListener) : RecyclerView.Adapter<ContentAdapter.ViewHolder>() {

override fun getItemCount(): Int = listOfData.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    var inf = ViewHolder(LayoutInflater.from(parent!!.context).inflate(R.layout.maintick, parent, false))
    return inf

}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    holder.bind(listOfData, listener)
}

class ViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView) {

    fun bind(listOfData: ArrayList<MainMarketTickClass>, listener: ContentListener) {
        val dataListin2 = listOfData[adapterPosition]

        itemView.textView.text = dataListin2.title

       interface method implemented in the Activity
        itemView.setOnClickListener {
            listener.onItemClicked(listOfData.get(adapterPosition))
        }
    }
}

public interface ContentListener {
    fun onItemClicked(item: MainMarketTickClass)
}

MainMarket.kt

class MainMarket: Fragment(),ContentAdapter.ContentListener{

var ITEMSList = ArrayList<MainMarketTickClass>()
companion object {
   fun newInstance():Fragment{

       var fb : MainMarket = MainMarket()
       return fb
   }
}


override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    var inf = inflater!!.inflate(R.layout.main_marker,container,false)
    return inf


}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

    ITEMSList .add ( MainMarketTickClass("123"))
    ITEMSList .add ( MainMarketTickClass(" 123"))
    ITEMSList .add ( MainMarketTickClass("123"))


    var adapter = ContentAdapter (MainActivity(),ITEMSList,this)
    list.adapter = adapter
    list.layoutManager = LinearLayoutManager(this.context,LinearLayoutManager.VERTICAL,false)

}

override fun onItemClicked(item: MainMarketTickClass) {
    if(activity is MainActivity){
        (activity as MainActivity).onItemClicked(item)

    }

}

addcar.kt

class AddCar: Fragment(), ContentAdapter.ContentListener{


companion object {
   fun newInstanceaddcar(): Fragment {

       var fb : AddCar = AddCar()
       val args = Bundle()

       fb.arguments = args

       return fb
   }
}





override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    return inflater!!.inflate(R.layout.add_car,container,false)



}

 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
     val TextView= view!!.findViewById(R.id.textView) as TextView
     var titlein = ""

}
override fun onItemClicked(item: MainMarketTickClass) {


}

Instead of passing the listOfData from your ContentAdapter to your ViewHolder , you should pass a single data of specific position to your ViewHolder . Here I make a change from your ContentAdapter :

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    holder.bind(listOfData[position], listener)
}

And than your ViewHolder should look like this:

class ViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView) {

    fun bind(data: MainMarketTickClass, listener: ContentListener) {
        itemView.setOnClickListener {
            listener.onItemClicked(data)
        }
    }
}

For transfering your data between fragment you may want to read Communicating with Other Fragments . Your ContentListener should be in MainMarket :

class MainMarket: Fragment() {
private lateinit var mCallback: ContentListener

// Container Activity must implement this interface
interface ContentListener {
    fun onItemClicked(item: String)
}

override fun onAttach(context: Context?) {
    super.onAttach(context)
    // This makes sure that the container activity has implemented
    // the callback interface. If not, it throws an exception
    try {
        mCallback = context as ContentListener
    } catch (e: ClassCastException) {
        throw ClassCastException(activity.toString()
                + " must implement OnHeadlineSelectedListener")
    }
}

And implement the ContentListener in your Activity

class MainActivity : AppCompatActivity(), MainMarket.ContentListener {

override fun onItemClicked(item: MainMarketTickClass) {
    val bundle = Bundle()
    bundle.putParcelable("data", item)

    val addCar = AddCar()
    addCar.arguments = bundle

    var ft : FragmentTransaction = supportFragmentManager.beginTransaction()
    ft.replace(R.id.frameLayout,addCar)
    ft.commit()
}

If you want to bring your object to another fragment, you should consider implementing your object with Parcelable . Here is some example for it Send object using parcelable .
Hope it will help you.

Here is a good tutorial that worked for me. In this tutorial, we create a bundle in the first fragment, then we put the that in this bundle. Finally we send the data to the second bundle using its arguments.

Kotlin Tutorial: Transfer data between Fragments -Android Studio Tutorials

The ways of passing data between fragments are:

  • Bundle (prefered)
  • SharedPreferences
  • Database

So, in your newInstanceaddcar(): Fragment pass as argument data you need, set is using bundle.putType() (where type is Int, Boolean, Serializable etc), and in your fragment code get those data using bundle.getType() . This way you can pass any serializable type to other fragment.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM