0

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) {


}
Twisha Kotecha
  • 1,082
  • 1
  • 4
  • 18
Nasser El Arab
  • 205
  • 2
  • 4
  • 10

3 Answers3

1

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.

Adn
  • 106
  • 3
  • i try to edit my code but onBindViewHolder that you type missing array list instance and if it work i send an array position im sill dont know how to get it from the fragment ca you show me pleas – Nasser El Arab Apr 15 '18 at 13:52
  • you may want to change your `bind()` parameter from `ViewHolder` to `bind(data: MainMarketTickClass, listener: ContentListener)`. I guess that your parameter still _ArrayList_. I change my answer and add the method to transfer between fragment. – Adn Apr 16 '18 at 01:12
  • thanks but now i Main Activity item not Parcelable what i do ? – Nasser El Arab Apr 16 '18 at 02:05
  • Your MainActivity must not be a parcelable. The one that should be parcelable is your data class which is `MainMarketTickClass`. You can either change it into parcelable or you can just add the data item one by one. Like `bundle.putStringExtra("name", data.getName())` – Adn Apr 16 '18 at 05:45
  • I trying every thing but send null every time – Nasser El Arab Apr 17 '18 at 13:00
  • Can you specify it to me which code that make NullPointerException? – Adn Apr 17 '18 at 13:51
  • When i get the arguments from the last Fragment and show it in ui it gave me null some one told me to change the data before send it like .toString il try this – Nasser El Arab Apr 17 '18 at 14:15
  • Just to pass data from one place to other, doing all this is going to hell and coming back :d – Aadam Oct 16 '21 at 13:42
1

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

double-beep
  • 5,031
  • 17
  • 33
  • 41
AMEL BENAIDA
  • 133
  • 1
  • 1
  • 9
  • 7
    A link to a solution is welcome, but please ensure your answer is useful without it: [add context around the link](//meta.stackexchange.com/a/8259) so your fellow users will have some idea what it is and why it’s there, then quote the most relevant part of the page you're linking to in case the target page is unavailable. [Answers that are little more than a link may be deleted.](//stackoverflow.com/help/deleted-answers) – double-beep Apr 01 '19 at 09:27
  • check my answer now , is it fine ? – AMEL BENAIDA Apr 01 '19 at 09:43
  • 2
    No, the edited answer is no better. An answer must include everything needed to answer the question without following a link to an external site. Links should only provide supplemental information. – greg-449 Apr 01 '19 at 10:13
0

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.

Cililing
  • 4,303
  • 1
  • 17
  • 35
  • i need to pass by click from adapter to next frag – Nasser El Arab Apr 15 '18 at 13:45
  • So I dont get where is your problem. You are able to pass data from adapter clicked to fragments which owns recyclerView. I mean `MainMarket.onItemClicked(item: MainMarketTickClass)` handles your clickes, and then you are invoking `MainActivity.onItemClicked(item: MainMarketTickClass)`. Now you want to pass those data to new fragment. So like I told, use Bundle, before opening new Fragment, pass those bundle into your new fragment (maybe by arguments in `newInstance()`?), and then open fragment and get your data. – Cililing Apr 15 '18 at 20:27