kotlin:如何在两个片段之间传递数据

Posted

技术标签:

【中文标题】kotlin:如何在两个片段之间传递数据【英文标题】:kotlin: how to pass a data between two fragments 【发布时间】:2018-09-25 00:29:48 【问题描述】:

我有一个简单的应用程序,它有一个 Activity 、 RecyclerView 适配器、 RecyclerView 片段和其他片段来显示我在 RecyclerView 中单击的那个项目的数据,但我的问题是我不知道如何传递数组行的数据新片段显示后的点击乐趣

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) 



【问题讨论】:

您可以使用 bundle 在片段之间轻松传递数据 【参考方案1】:

您应该将特定位置的单个数据传递给您的ViewHolder,而不是将ContentAdapter 中的listOfData 传递给ViewHolder。这里我对你的ContentAdapter做一个修改:

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

你的ViewHolder 应该是这样的:

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

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

要在片段之间传输数据,您可能需要阅读 Communicating with Other Fragments。你的ContentListener 应该在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")
    

并在您的Activity 中实现ContentListener

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

如果你想把你的对象带到另一个片段,你应该考虑用Parcelable来实现你的对象。这是Send object using parcelable 的一些示例。 希望对你有帮助。

【讨论】:

我尝试编辑我的代码,但是 onBindViewHolder 你输入了缺少的数组列表实例 如果它工作我发送一个数组位置我仍然不知道如何从你显示的片段我请 您可能希望将您的bind() 参数从ViewHolder 更改为bind(data: MainMarketTickClass, listener: ContentListener)。我猜你的参数仍然是ArrayList。我更改了答案并添加了在片段之间传输的方法。 谢谢,但现在我的主要活动项目不可打包,我该怎么办? 您的 MainActivity 不能是 parcelable。应该可以打包的是您的数据类MainMarketTickClass。您可以将其更改为可打包的,也可以仅将数据项一一添加。喜欢bundle.putStringExtra("name", data.getName()) 我尝试了所有事情,但每次都发送 null【参考方案2】:

这是一个对我有用的好教程。在本教程中,我们在第一个片段中创建一个包,然后我们将其放入该包中。最后,我们使用它的参数将数据发送到第二个包。

Kotlin Tutorial: Transfer data between Fragments -android Studio Tutorials

【讨论】:

欢迎提供解决方案链接,但请确保您的答案在没有它的情况下有用:add context around the link 这样您的其他用户就会知道它是什么以及为什么会出现,然后引用最相关的您链接到的页面的一部分,以防目标页面不可用。 Answers that are little more than a link may be deleted. 现在检查我的答案,好吗? 不,编辑后的答案也好不到哪里去。答案必须包括回答问题所需的所有内容,而无需点击外部站点的链接。链接只能提供补充信息。【参考方案3】:

片段之间传递数据的方式有:

捆绑(首选) 共享首选项 数据库

因此,在您的newInstanceaddcar(): Fragment 作为您需要的参数数据传递中,set 使用bundle.putType()(其中类型为 Int、Boolean、Serializable 等),并在您的片段代码中使用bundle.getType() 获取这些数据。 这样您就可以将任何可序列化类型传递给其他片段。

【讨论】:

我需要通过点击从适配器传递到下一个片段 所以我不明白你的问题在哪里。您可以将单击的适配器中的数据传递给拥有 recyclerView 的片段。我的意思是MainMarket.onItemClicked(item: MainMarketTickClass) 处理您的点击,然后您调用MainActivity.onItemClicked(item: MainMarketTickClass)。现在您想将这些数据传递给新片段。所以就像我说的那样,使用 Bundle,在打开新的 Fragment 之前,将这些 bundle 传递到你的新 Fragment 中(可能通过 newInstance() 中的参数?),然后打开 Fragment 并获取你的数据。

以上是关于kotlin:如何在两个片段之间传递数据的主要内容,如果未能解决你的问题,请参考以下文章

通过适配器在片段之间传递数据(Kotlin Android)

如何在导航抽屉中的两个片段之间传递数据

在两个以上片段之间传递数据

如何将数据从 Intent 传递到 Fragment

在片段之间传递数据

如何将editText值传递给viewModel和Livedata(Kotlin)