前言

本文主要记录activity、fragment之中的参数传递,包括各自的跳转传递,返回后的参数传递,以及之间的互相传递等,本文后续会持续更新记录。


一、activity数据传递篇

1.activity传递给activity时

  • 使用Inten的putExtra传递
页面A:
 val intent = Intent(this, BActivity::class.java).apply { putExtra("key","A页面的数据")}
  startActivity(intent)
页面B:
  val data = intent.getStringExtra("key")
    textTest.text = data
  • 使用Inten的Bundle传递
页面A:
  val intent = Intent(this, BActivity::class.java).apply {
        val bundle = Bundle().apply {
          putString("bundle","A页面的数据2")
                }
          putExtra("key",bundle)
            }
  startActivity(intent)

页面B:
val data = intent.getBundleExtra("key")?.getString("bundle")
  textTest.text = data


  • 使用SharedPreferences(目前已淘汰,可使用MMKV)
页面A:
  //访问模式为当前应用可访问
val shreadprefrence = this.getSharedPreferences("value", Context.MODE_PRIVATE)
  //获取编辑器
val editor = shreadprefrence.edit()
   editor.putString("key","这是A页面的数据3")
   editor.commit() //同步提交有返回值, apply()异步提交没有返回值
 startActivity(Intent(this, BActivity::class.java))
 
页面B:
val sp = this.getSharedPreferences("value", Context.MODE_PRIVATE)
  val data = sp.getString("key", "")
  textTest.text = data
MMKV版:
MMKV地址:https://github.com/Tencent/MMKV/wiki/android_tutorial_cn
 
模块build中添加依赖:implementation 'com.tencent:mmkv:2.2.4'

自定义Application中进行初始化:
class Application : Application() {
    override fun onCreate() {
        super.onCreate()
        //app启动时进行初始化,默认将文件存放在$(FilesDir)/mmkv/目录
       val rootDir  = MMKV.initialize(this) //此处可以获取到默认的目录

        //也可以自定义目录
      /*  val dir = getFilesDir().getAbsolutePath() + "/mmkv"
        val rootDir = MMKV.initialize(dir)*/
    }
}

清单文件中将自定义application添加:
  <application
        android:name=".Application"
        ....../>

页面A:
  //mmkv对象的获取方式
 val mmkv = MMKV.defaultMMKV() //获取默认的全局实例,常用
 val mmkv1 = MMKV.mmkvWithID("id") //有不同的业务需要区别存储时,通过ID创建自定义mmkv对象
 val mmkv2 = MMKV.mmkvWithID("id",MMKV.MULTI_PROCESS_MODE) //需要多进程访问时
  //添加
mmkv.encode("key","这是mmkv存储的数据")
startActivity(Intent(this, BActivity::class.java))


页面B:
val data = MMKV.defaultMMKV().decodeString("key")//取值
textTest.text = data //展示
MMKV.defaultMMKV().removeValueForKey("key") //一次性使用时可以清除掉


**将之前sp数据迁移到MMKV时:**
 //将数据从之前的SP中迁移过来
val mmkvData = MMKV.mmkvWithID("myData")
val olderData = getSharedPreferences("myData", MODE_PRIVATE)
mmkv.importFromSharedPreferences(olderData)
olderData.edit().clear().commit()

  //后面添加数据的用法跟sp一样不用改
val editor: SharedPreferences.Editor = mmkvData.edit()
editor.putBoolean("bool", true)
editor.putInt("int", Int.Companion.MIN_VALUE) 
//editor.commit()//不需要commit

  • 使用序列化对象Seriazable
定义数据类并进行序列化:
data class DataBean (val id:Int,val name: String): Serializable //进行序列化

页面A:
val intent =Intent(this, BActivity::class.java)
 intent.putExtra("key", DataBean(5, "张三"))
 startActivity(intent)
            
页面B:
val data = intent.getSerializableExtra("key") as DataBean
 textTest.text = "${data.id}${data.name}"
            
  • 使用静态变量传递数据
定义静态变量:
 companion object{
        var data: String = ""
    }
页面A:
val intent = Intent(this, BActivity::class.java)
    BActivity.data = "这是展示的数据"
    startActivity(intent)
页面B:
  textTest.text = data //因此该静态变量定义在了页面B中

2.activity传递给fragment时

  • 利用动态创建fragment时传递bundle
activity页面:
    //传递
        val fragment = TestFragment().apply {
            arguments = Bundle().apply {
                putString("key", "传递给fragment的数据")
            }
        }
        //开启
        supportFragmentManager.beginTransaction().add(R.id.frame, fragment).commit()


fragment页面:
override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_test, container, false)

        val textView = view.findViewById<TextView>(R.id.text_fragment)
        val data = arguments?.getString("key") //取值

        textView.text = data
        return view
    }

  • 通过fragment的工厂方法进行传递
activity页面:
    //初始化并进行传递
val fragment = TestFragment.newInstance("静态方法从fragment中添加的数据")
    //开启
supportFragmentManager.beginTransaction().add(R.id.frame, fragment).commit()


fragment页面:
 companion object{ //使用工厂方法创建fragment并传值
        @JvmStatic
        fun newInstance(data:String): TestFragment = TestFragment().apply {
            arguments = Bundle().apply {
                putString("key",data)
            }
        }
    }
 private fun initView(view: View) { 
        textView = view.findViewById(R.id.text_fragment)
        val data = arguments?.getString("key") //取值
        textView.text = data
    }


  • fragment通过获取宿主activity进而调用宿主方法来取值
activity页面:
 fun getVaule(): String = "通过activity的方法传递的数据"
 
  //初始化并进行传递
val fragment = TestFragment()
  //开启
 supportFragmentManager.beginTransaction().add(R.id.frame, fragment).commit()


fragment页面:
textView = view.findViewById(R.id.text_fragment)
        val data = (context as MainActivity).getVaule()
        textView.text = data
  • 通过viewModel来数据共享
创建viewModel:
class SharedViewModel : ViewModel() {

    private val _userData = MutableLiveData<UserData>() //确保可写只能在该类中操作
    val userData: LiveData<UserData> = _userData

    fun setUserData(data: UserData){
        _userData.value = data
    }
}
data class UserData(val name: String)


activity页面:
private lateinit var  sharedViewModel : SharedViewModel
          ......
sharedViewModel = ViewModelProvider(this).get(SharedViewModel::class.java)
sharedViewModel.setUserData(UserData("阿李"))//设置传递的数据
supportFragmentManager.beginTransaction().add(R.id.frame, TestFragment()).commit()//开启


fragment页面:
 private lateinit var sharedViewModel: SharedViewModel
    private fun initView(view: View) {
        textView = view.findViewById(R.id.text_fragment)

        //此处用requireActivity确保获取到是同一个实例
        sharedViewModel = ViewModelProvider(owner = requireActivity()).get(SharedViewModel::class.java)
        sharedViewModel.userData.observe(viewLifecycleOwner){userData ->
            textView.text = userData.name
        }
        
    }
  • 使用接口回调
创建一个接口:
interface DataTransferListener {
    fun onDataReceived(name: String, age: Int) //接收fragment的信息
    fun getCurrentData(): Pair<String, Int> //向fragment发送
}


activity页面:
class MainActivity : AppCompatActivity(), DataTransferListener{ //实现该接口
    private lateinit var btnQueding: Button
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        btnQueding = findViewById(R.id.btn_tiaozhuan)
        btnQueding.setOnClickListener {
            //开启
        supportFragmentManager.beginTransaction().add(R.id.frame, TestFragment()).commit()
        }
    }
    override fun onDataReceived(name: String, age: Int) { //获取fragment传递过去的数据
        Toast.makeText(this,"$name+$age", Toast.LENGTH_SHORT).show()
    }
    override fun getCurrentData(): Pair<String, Int> = Pair("张三",19)
}


fragment页面:
class TestFragment : Fragment() {

    private lateinit var textView: TextView
    private lateinit var button: Button
    
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_test, container, false)
        initView(view)
        return view
    }
    private var dataListener: DataTransferListener? = null
    
    override fun onAttach(context: Context) { //附加到activity之后就可以将子类activity进行实例化
        super.onAttach(context)
        dataListener = context as DataTransferListener
    }
    
    private fun initView(view: View) {
        textView = view.findViewById(R.id.text_fragment)
        button = view.findViewById(R.id.btn_fragment)

        textView.text = dataListener?.getCurrentData().toString() //获取值
        button.setOnClickListener { //传递值
            dataListener?.onDataReceived("123",12)
        }
    }
     override fun onDetach() {
        super.onDetach()
        if(dataListener != null) dataListener = null //避免内存泄漏
    }
}

3.子activity需要返回数据时

- registerForActivityResult 方式
最新的推荐方式,避免了以前方式的结构不合理性

1.定义ActivityResultLauncher来处理返回的数据
private val launcher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == Activity.RESULT_OK){
val data = result.data?.getStringExtra(“key”)
Toast.makeText(this, “当前获取的返回数据是:${data.toString()}”, Toast.LENGTH_SHORT)
.show()
}
}
2.启动子Acitivity
launcher.launch(Intent(this, BActivity::class.java))
3.子页面中传递数据
val intent = Intent().apply {
putExtra(“key”,“BActivity页面的数据2”)
}
setResult(Activity.RESULT_OK,intent) //这是返回数据
finish()

此外还支持多种ActivityResultContracts甚至自定义:
ActivityResultContracts.RequestPermission()(请求单个权限)
ActivityResultContracts.GetContent()(选择文件)
ActivityResultContracts.TakePicture()(拍照)
具体更多使用方式参考:https://juejin.cn/post/7504911900556984354

案例:

主页面:
class MainActivity : AppCompatActivity() {

    private lateinit var btnQueding: Button

    //申明launcher来获取返回值,这里直接使用官方定义好的StartActivityForResult类
    private val launcher =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            if (result.resultCode == Activity.RESULT_OK){
                val data = result.data?.getStringExtra("key")
                Toast.makeText(this, "当前获取的返回数据是:${data.toString()}", Toast.LENGTH_SHORT)
                    .show()
            }
        }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        btnQueding = findViewById(R.id.btn_tiaozhuan)
        btnQueding.setOnClickListener {
            //方法1:传统的startActivityForResult 已废弃
           // startActivityForResult(Intent(this, BActivity::class.java), REQUEST_CODE)
           //方法2:registerForActivityResult
            launcher.launch(Intent(this, BActivity::class.java))
        }

    }
}

子页面
class BActivity : AppCompatActivity() {

    private lateinit var btnTiaozhuan: Button
    private lateinit var toolbar: Toolbar

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge() //沉浸式
        setContentView(R.layout.activity_b)

        //对内容区域设置边界
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }

        initView()
    }

    private fun initView() {
        btnTiaozhuan = findViewById(R.id.btn_bactivity)
        btnTiaozhuan.setOnClickListener {
            startActivity(Intent(this, MainActivity::class.java))
        }

        toolbar = findViewById(R.id.toolbar_b)
        /**
         * 返回键生效必要步骤
         */
        setSupportActionBar(toolbar) //1.设置actionbar为当前toolbar
        supportActionBar?.setDisplayHomeAsUpEnabled(true) //2.设置返回键启用
        toolbar.setNavigationOnClickListener {


            //处理返回数据的逻辑不变
            val intent = Intent().apply {
                putExtra("key","BActivity页面的数据2")
            }
            setResult(Activity.RESULT_OK,intent) //这是返回数据
            finish() //结束
        }
    }
}

- 传统的startActivityForResult(已废弃):

1. A页面开启请求,需要请求码
startActivityForResult(Intent(this, BActivity::class.java), REQUEST_CODE)

2.B页面结束时返回数据
val intent = Intent()
intent.putExtra(“key”,“BActivity页面的数据”)
setResult(RESULT_OK,intent) //这是返回数据
finish() //结束

3.A重写onActivityResult中接收
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_CODE && resultCode == BActivity.RESULT_OK) {
val data = data?.getStringExtra(“key”)
Toast.makeText(this, “当前获取的返回数据是:${data.toString()}”, Toast.LENGTH_SHORT)
.show()
}
}

案例:

页面A
class MainActivity : AppCompatActivity() {

    

companion object {
        const val REQUEST_CODE = 0
    }

    private lateinit var btnQueding: Button

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        btnQueding = findViewById(R.id.btn_tiaozhuan)
        btnQueding.setOnClickListener {
            //方法1:传统的startActivityForResult 已废弃
       startActivityForResult(Intent(this, BActivity::class.java), REQUEST_CODE)
        }

    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if (requestCode == REQUEST_CODE && resultCode == BActivity.RESULT_OK) {
            val data = data?.getStringExtra("key")
            Toast.makeText(this, "当前获取的返回数据是:${data.toString()}", Toast.LENGTH_SHORT)
                .show()
        }
    }
}

页面B
class BActivity : AppCompatActivity() {

    companion object{
        const val RESULT_OK = 1
    }

    private lateinit var btnTiaozhuan: Button
    private lateinit var toolbar: Toolbar

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge() //沉浸式
        setContentView(R.layout.activity_b)

        //对内容区域设置边界
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }

        initView()
    }

    private fun initView() {
        btnTiaozhuan = findViewById(R.id.btn_bactivity)
        btnTiaozhuan.setOnClickListener {
            startActivity(Intent(this, MainActivity::class.java))
        }

        toolbar = findViewById(R.id.toolbar_b)
        /**
         * 返回键生效必要步骤
         */
        setSupportActionBar(toolbar) //1.设置actionbar为当前toolbar
        supportActionBar?.setDisplayHomeAsUpEnabled(true) //2.设置返回键启用
        toolbar.setNavigationOnClickListener {
            val intent = Intent()
            intent.putExtra("key","BActivity页面的数据")
            setResult(RESULT_OK,intent) //这是返回数据
            finish() //结束
        }


    }
}

页面b的布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".ui.BActivity">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar_b"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        app:title=" "
        android:navigationIcon="@drawable/arrow_back"
        >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="BActivity"
            android:layout_gravity="center_horizontal"
            />
    </androidx.appcompat.widget.Toolbar>

    <Button
        android:id="@+id/btn_bactivity"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="返回上一级activity"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="50dp"
        />

</LinearLayout>

二、fragment数据传递篇

1.fragment传递给activity时

  • 使用接口回调(常用)
接口:
interface DataInterfaceListener {
    fun dataUpdate(data:String)
}


fragment页面:
class AFragment : Fragment() {
    private lateinit var textFragmentA: TextView
    private lateinit var btnFragmentA: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_a, container, false)
        initView(view)
        return view
    }
    
    private var dataInterfaceListener: DataInterfaceListener? = null
    override fun onAttach(context: Context) {
        super.onAttach(context)
      dataInterfaceListener =  context as? MainActivity //1.接口子类初始化
         //防止转化异常
        if(dataInterfaceListener == null) throw ClassCastException("$context must implement DataInterfaceListener")
    }
    override fun onDetach() {
        super.onDetach()
         //指控避免内存泄漏
        if(dataInterfaceListener != null) dataInterfaceListener = null
    }

    private fun initView(view: View) {
        textFragmentA = view.findViewById(R.id.text_fragment_A)
        btnFragmentA = view.findViewById(R.id.btn_fragment_a)

        btnFragmentA.setOnClickListener {
            //2.传值
            dataInterfaceListener?.dataUpdate("fragment页面的数据")
        }
    }
}




activity页面:
class MainActivity : AppCompatActivity(), DataInterfaceListener{ //实现接口并重写方法
    private lateinit var btnQueding: Button
    private lateinit var textMain: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initView()
        initListener()
    }
    private fun initView() {
        btnQueding = findViewById(R.id.btn_tiaozhuan)
        textMain = findViewById(R.id.main_text)
    }
    private fun initListener() {

        btnQueding.setOnClickListener { //点击后开启fragment
            supportFragmentManager.beginTransaction()
                .add(R.id.frame_a, AFragment())
                .commit()
        }
    }

    override fun dataUpdate(data: String) { //接口的方法
            textMain.text = data //获取值
    }
}
  • 使用ViewModel(复杂场景使用)

实例化viewmodel对象时的方法需要引入扩展函数的依赖
implementation “androidx.activity:activity-ktx:1.8.1”
implementation “androidx.fragment:fragment-ktx:1.6.2”

viewmodel类:
class SharedViewModel : ViewModel() {
    private val _data: MutableLiveData<Event<UserData>> = MutableLiveData<Event<UserData>>()
    val data: LiveData<Event<UserData>> = _data //只保留可读供外部调用
    fun sendDataFromFragment(data: UserData){
        _data.value = Event(data) //每次设置新数据都会创建新的实例,只有屏幕旋转等操作才会触发旧数据的重复接收
    }
}

/**
 * 包装器,防止配置更改等造成数据重复接收,解决数据倒灌
 */
class Event<T>(private val content: T) {
    private var hasBeenHandled = false
    fun getContentIfNotHandled(): T? {
        return if (hasBeenHandled) null
        else {
            hasBeenHandled = true
            content
        }
    }
}
/**
 * 数据类
 */
data class UserData(
    val type: String,
    val payload: Any?
)



fragment页面:
class AFragment : Fragment() {
    private lateinit var textFragmentA: TextView
    private lateinit var btnFragmentA: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_a, container, false)
        initView(view)
        return view
    }

    //1.实例化附属activity的viewmodel
    private val sharedViewModel: SharedViewModel by activityViewModels()

    private fun initView(view: View) {
        textFragmentA = view.findViewById(R.id.text_fragment_A)
        btnFragmentA = view.findViewById(R.id.btn_fragment_a)

        btnFragmentA.setOnClickListener {
            //2.传值
          sharedViewModel.sendDataFromFragment(UserData("name","小李"))
        }
    }
}



activity页面:
class MainActivity : AppCompatActivity(){
    private lateinit var btnQueding: Button
    private lateinit var textMain: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initView()
        initListener()
    }
    //1.实例化当前页面的viewmodel
    private val sharedViewModel: SharedViewModel by viewModels()
    private fun initView() {
        btnQueding = findViewById(R.id.btn_tiaozhuan)
        textMain = findViewById(R.id.main_text)

        //2.监听用来接收数据
        sharedViewModel.data.observe(this){ event ->
            event.getContentIfNotHandled()?.let { data ->
                when(data.type){
                    "name" ->{
                        val content = data.payload as String
                        textMain.text = content
                    }
                }
            }
        }
    }
    private fun initListener() {
        btnQueding.setOnClickListener { //点击后开启fragment
            supportFragmentManager.beginTransaction()
                .add(R.id.frame_a, AFragment())
                .commit()
        }
    }
}

  • 使用EventBus

需要引入依赖:
implementation ‘org.greenrobot:eventbus:3.3.1’
EventBus的详细使用可参考:https://juejin.cn/post/7526417144490737705

定义的事件:
data class DataBean (val id:Int,val name: String) //1.创建实体类来盛放数据


fragment页面:
class AFragment : Fragment() {
    private lateinit var textFragmentA: TextView
    private lateinit var btnFragmentA: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_a, container, false)
        initView(view)
        return view
    }
    private fun initView(view: View) {
        textFragmentA = view.findViewById(R.id.text_fragment_A)
        btnFragmentA = view.findViewById(R.id.btn_fragment_a)

        btnFragmentA.setOnClickListener {
            //发布
            EventBus.getDefault().post(DataBean(12,"小李"))
            //发布粘性事件
           // EventBus.getDefault().postSticky(DataBean(12,"小李"))
        }
    }
}



activity页面:
class MainActivity : AppCompatActivity(){
    private lateinit var btnQueding: Button
    private lateinit var textMain: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initView()
        initListener()
    }
    override fun onStart() {
        super.onStart()
        //2.注册订阅者
        EventBus.getDefault().register(this)
    }
    override fun onStop() {
        super.onStop()
        EventBus.getDefault().unregister(this) //需要及时注销
    }

    /**
     * 3.声明事件的处理方法
     * 需要注释为Subscribe,且有两个参数可选择
     *  threadMode: 必选
     *      ThreadMode.POSTING->默认,该方法在事件发布所在的线程中执行
     *      ThreadMode.MAIN->该方法在主线程中执行
     *      ThreadMode.MAIN_ORDERED->该方法在主线程中执行,且按照顺序执行
     *      ThreadMode.BACKGROUND->后台线程调用,会调用单一的后台线程池,适合轻量级操作
     *      ThreadMode.ASYNC->在独立 非主线程 非发布线程调用,使用线程池执行,适合耗时操作
     *  sticky: 可选
     *      false-> 默认,不处理粘性事件
     *      true->处理粘性事件,可以在先发布后订阅时也能获取到最新数据
     */
   @Subscribe(threadMode = ThreadMode.MAIN)
    fun setData(data: DataBean){
        textMain.text = "${data.id}-${data.name}"
    }

    private fun initView() {
        btnQueding = findViewById(R.id.btn_tiaozhuan)
        textMain = findViewById(R.id.main_text)
    }
    private fun initListener() {
        btnQueding.setOnClickListener { //点击后开启fragment
            supportFragmentManager.beginTransaction()
                .add(R.id.frame_a, AFragment())
                .commit()
        }
    }
}

2.fragment传递给fragment时

  • 通过Bundle传值(启动时传递给子fragment)
activity页面:
class MainActivity : AppCompatActivity() { //只开启父页面fragment
    private lateinit var btnQueding: Button
    private lateinit var textMain: TextView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initView()
        initListener()
    }
    private fun initView() {
        btnQueding = findViewById(R.id.btn_tiaozhuan)
        textMain = findViewById(R.id.main_text)
    }
    private fun initListener() {
        btnQueding.setOnClickListener { //点击后开启fragment
            supportFragmentManager.beginTransaction()
                .add(R.id.frame_a, AFragment())
                .commit()
        }
    }
}


父fragment页面:
class AFragment : Fragment() {
    private lateinit var textFragmentA: TextView
    private lateinit var btnFragmentA: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_a, container, false)
        initView(view)
        return view
    }
    private fun initView(view: View) {
        textFragmentA = view.findViewById(R.id.text_fragment_A)
        btnFragmentA = view.findViewById(R.id.btn_fragment_a)

        btnFragmentA.setOnClickListener {
             val fragmentB = BFragment()
            //传值
            fragmentB.arguments = bundleOf("name" to "小李子")
            //开启子fragment
            parentFragmentManager.beginTransaction().replace(R.id.frame_b,fragmentB)
                .commit()
        }
    }
}



子fragment页面:
class BFragment : Fragment() {
    private lateinit var textFragmentB: TextView
    private lateinit var btnFragmentB: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_b, container, false)
        initView(view)

        initData()
        return view
    }
    private fun initData() {
        //获取父fragment传递过来的数据
       textFragmentB.text = arguments?.getString("name")
    }
    private fun initView(view: View) {
        textFragmentB = view.findViewById(R.id.text_fragment_b)
        btnFragmentB = view.findViewById(R.id.btn_fragment_b)
    }
}

  • 通过Serializable来传递对象(启动时传递给子Fragment)
序列化对象;
data class DataBean (val id:Int,val name: String): Serializable //进行序列化


activity页面:
class MainActivity : AppCompatActivity() { //只开启父页面fragment
    private lateinit var btnQueding: Button
    private lateinit var textMain: TextView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initView()
        initListener()
    }
    private fun initView() {
        btnQueding = findViewById(R.id.btn_tiaozhuan)
        textMain = findViewById(R.id.main_text)
    }
    private fun initListener() {
        btnQueding.setOnClickListener { //点击后开启fragment
            supportFragmentManager.beginTransaction()
                .add(R.id.frame_a, AFragment())
                .commit()
        }
    }
}


父fragment页面:
class AFragment : Fragment() { //父fragment
    private lateinit var textFragmentA: TextView
    private lateinit var btnFragmentA: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_a, container, false)
        initView(view)
        return view
    }
    private fun initView(view: View) {
        textFragmentA = view.findViewById(R.id.text_fragment_A)
        btnFragmentA = view.findViewById(R.id.btn_fragment_a)

        btnFragmentA.setOnClickListener {
             val fragmentB = BFragment()
            
            fragmentB.arguments = Bundle().apply {
                //传递序列化之后的对象
                putSerializable("key", DataBean(12,"小李"))
            }
            //开启子fragment
            parentFragmentManager.beginTransaction().replace(R.id.frame_b,fragmentB)
                .commit()
        }
    }
}



子fragment页面:
class BFragment : Fragment() {
    private lateinit var textFragmentB: TextView
    private lateinit var btnFragmentB: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_b, container, false)
        initView(view)

        initData()
        return view
    }
    private fun initData() {
        //获取父fragment传递过来的序列化对象
        val data = arguments?.getSerializable("key") as DataBean
       textFragmentB.text = "${data.id}-${data.name}"
    }
    private fun initView(view: View) {
        textFragmentB = view.findViewById(R.id.text_fragment_b)
        btnFragmentB = view.findViewById(R.id.btn_fragment_b)
    }
}
  • 通过activity来中转(传统,无需父子关系)
activity页面:
class MainActivity : AppCompatActivity() { //开启两个交互的fragment页面
    private lateinit var btnQueding: Button
    private lateinit var textMain: TextView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initView()
        initListener()
    }
    private fun initView() {
        btnQueding = findViewById(R.id.btn_tiaozhuan)
        textMain = findViewById(R.id.main_text)
    }
    private fun initListener() {
        btnQueding.setOnClickListener { //点击后开启fragment
            supportFragmentManager.beginTransaction()
                .add(R.id.frame_a, AFragment())
                .add(R.id.frame_b, BFragment())
                .commit()
        }
    }
}



fragment页面A:
class AFragment : Fragment() {
    private lateinit var textFragmentA: TextView
    private lateinit var btnFragmentA: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_a, container, false)
        initView(view)
        return view
    }
    private fun initView(view: View) {
        textFragmentA = view.findViewById(R.id.text_fragment_A)
        btnFragmentA = view.findViewById(R.id.btn_fragment_a)

        btnFragmentA.setOnClickListener {
            //传递给并列的另一个fragment
           val fragment = activity?.supportFragmentManager?.findFragmentById(R.id.frame_b) as BFragment
            fragment.updateB("A页面传递的数据")
        }
    }
    fun updateA(data:String){ //对外提供获取数据的方法
        textFragmentA.text = data
    }
}


fragment页面B:
class BFragment : Fragment() {
    private lateinit var textFragmentB: TextView
    private lateinit var btnFragmentB: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_b, container, false)
        initView(view)

        initData()
        return view
    }
    private fun initData() {
        btnFragmentB.setOnClickListener {
            //传递给A页面
           val fragment = activity?.supportFragmentManager?.findFragmentById(R.id.frame_a) as AFragment
            fragment.updateA("B页面传递的数据")
        }
    }
    private fun initView(view: View) {
        textFragmentB = view.findViewById(R.id.text_fragment_b)
        btnFragmentB = view.findViewById(R.id.btn_fragment_b)
    }
    fun updateB(data:String){ //对外提供获取数据的方法
        textFragmentB.text = data
    }
}
  • 使用中介接口
接口:
interface FragmentMediator {
    fun sendDataToFragmentB(data: String) //用于fragmentA与activity交互后传值
    fun sendDataToFragmentA(data: String) //用于fragmentB与activity交互后传值
}


activity页面:
class MainActivity : AppCompatActivity(), FragmentMediator { //开启两个交互的fragment页面
    private lateinit var btnQueding: Button
    private lateinit var textMain: TextView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initView()
        initListener()
    }
    private fun initView() {
        btnQueding = findViewById(R.id.btn_tiaozhuan)
        textMain = findViewById(R.id.main_text)
    }
    private lateinit var fragmentA: AFragment
    private lateinit var fragmentB: BFragment
    private fun initListener() {
        btnQueding.setOnClickListener { //点击后开启fragment

            fragmentA = AFragment()
            fragmentB = BFragment()

            supportFragmentManager.beginTransaction()
                .add(R.id.frame_a, fragmentA)
                .add(R.id.frame_b, fragmentB)
                .commit()
        }
    }
    /**
     * 重写该方法给A页面调用然后此处中转给B页面
     */
    override fun sendDataToFragmentB(data: String) {
        fragmentB.updateB(data)
    }
    /**
     * 重写该方法给B页面调用然后此处中转给A页面
     */
    override fun sendDataToFragmentA(data: String) {
        fragmentA.updateA(data)
    }
}



fragment页面A:
class AFragment : Fragment() {
    private lateinit var textFragmentA: TextView
    private lateinit var btnFragmentA: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_a, container, false)
        initView(view)
        initListener()
        return view
    }
    private fun initView(view: View) {
        textFragmentA = view.findViewById(R.id.text_fragment_A)
        btnFragmentA = view.findViewById(R.id.btn_fragment_a)
    }
    private var fragmentMediator: FragmentMediator? = null
    override fun onAttach(context: Context) {
        super.onAttach(context)
        fragmentMediator = context as? FragmentMediator //接口子类实例化
        if(fragmentMediator == null) throw ClassCastException("$context must implement FragmentMediator")
    }
    override fun onDetach() {
        super.onDetach()
        if(fragmentMediator != null) fragmentMediator =null //置空防止内存泄漏
    }
    private fun initListener() {
        btnFragmentA.setOnClickListener {
            fragmentMediator?.sendDataToFragmentB("页面A的数据")
        }
    }
    fun updateA(data:String){ //对外提供获取数据的方法
        textFragmentA.text = data
    }
}



fragment页面B:
class BFragment : Fragment() {
    private lateinit var textFragmentB: TextView
    private lateinit var btnFragmentB: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_b, container, false)
        initView(view)
        initListener()
        return view
    }

    private fun initView(view: View) {
        textFragmentB = view.findViewById(R.id.text_fragment_b)
        btnFragmentB = view.findViewById(R.id.btn_fragment_b)
    }
    private var fragmentMediator: FragmentMediator? = null
    override fun onAttach(context: Context) {
        super.onAttach(context)
        fragmentMediator = context as? FragmentMediator //接口子类实例化
        if(fragmentMediator == null) throw ClassCastException("$context must implement FragmentMediator")
    }
    override fun onDetach() {
        super.onDetach()
        if(fragmentMediator != null) fragmentMediator = null //指控防止内存泄漏
    }
    private fun initListener() {
        btnFragmentB.setOnClickListener {
            fragmentMediator?.sendDataToFragmentA("页面B传递的数据")
        }
    }
    fun updateB(data: String) { //对外提供获取数据的方法
        textFragmentB.text = data
    }
}
  • 用Jetpack navigation框架进行传递

详细使用可参考:https://blog.csdn.net/yingaizhu/article/details/105972720%20%20https://unlockdoc.smain.cn/online/2025-11-14/6016430b496eb557a47195eb57e6fcda.html

1.使用bundle进行简单数据传递

创建导航图:
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_graph"
    app:startDestination="@id/fragment_a">

    <!--传递的fragmentA
    label:fragment的标签
         layout:关联的布局
         name:关联的fragment-->
    <fragment
        android:id="@+id/fragment_a"
        android:name="com.byb.myphonevideo.ui.fragment.AFragment"
        android:label="Afragment"
        tools:layout="@layout/fragment_a">
        <!--设置跳转动作
        destination:跳转的目的地 -->
        <action
            android:id="@+id/fragmentA_to_fragmentB"
            app:destination="@id/fragment_b" />
    </fragment>

    <fragment
        android:id="@+id/fragment_b"
        android:label="BFragment"
        android:name="com.byb.myphonevideo.ui.fragment.BFragment"
        tools:layout="@layout/fragment_b"/>
</navigation>



activity的xml页面中添加导航宿主(代码页无需额外设置)<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".ui.MainActivity">
    
    <!--navigation中添加NavHostFragment控件作为导航宿主
    name:此处为默认实现,也可使用自定以的fragment,但必须实现NavHost或继承NavHostFragment
    navGrap:将当前的导航宿主与导航图相关联
    defaultNavHost:是否由导航宿主拦截返回事件,true时则返回键按下不会直接推出附加的activity
    -->
  <fragment
      android:id="@+id/fragment_nav"
      android:layout_width="match_parent"
      android:layout_height="500dp"
      android:name="androidx.navigation.fragment.NavHostFragment"
      app:defaultNavHost="true"
      app:navGraph="@navigation/nav_graph"
      />
    
    <Button
        android:id="@+id/btn_tiaozhuan"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="@string/btn_text" />

    <TextView
        android:id="@+id/main_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="30dp"
        android:text="@string/app_name" />
</LinearLayout>



fragment页面A:
class AFragment : Fragment(){
    private lateinit var textFragmentA: TextView
    private lateinit var btnFragmentA: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_a, container, false)
        initView(view)
        initListener()
        return view
    }
    private fun initView(view: View) {
        textFragmentA = view.findViewById(R.id.text_fragment_A)
        btnFragmentA = view.findViewById(R.id.btn_fragment_a)
    }

    private fun initListener() {
        btnFragmentA.setOnClickListener {
            //使用控制器来进行跳转的动作,同时传递参数,只适用少量数据传递
            val findNavController = findNavController()
            findNavController.navigate(R.id.fragmentA_to_fragmentB, Bundle().apply {
                putString("key","页面A传递的数据")
            })
        }
    }
}


fragment页面B:
class BFragment : Fragment() {
    private lateinit var textFragmentB: TextView
    private lateinit var btnFragmentB: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_b, container, false)
        initView(view)
        initListener()
        return view
    }

    private fun initView(view: View) {
        textFragmentB = view.findViewById(R.id.text_fragment_b)
        btnFragmentB = view.findViewById(R.id.btn_fragment_b)
    }

    private fun initListener() {
        //获取传递过来的参数
        val data = arguments?.getString("key")
        textFragmentB.text = data
    }
}

2.使用推荐的safeArgs方式传安全递数据

添加完依赖并设置好导航图中的参数后需要rebuild,以便插件生成对应的文件
在这里插入图片描述

项目级settings.gradle中增加配置:
pluginManagement {
    repositories {
        google {
            content {
                includeGroupByRegex("com\\.android.*")
                includeGroupByRegex("com\\.google.*")
                includeGroupByRegex("androidx.*")
            }
        }
        mavenCentral()
        gradlePluginPortal()
    }
    plugins {
        //navigation中安全传递参数的Safe Args 插件
        id("androidx.navigation.safeargs.kotlin") version "2.5.2"
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
    }
}
rootProject.name = "TestApplication"
include ':app'


模块级build.gradle配置中增加:
plugins {
    alias(libs.plugins.android.application)
    alias(libs.plugins.kotlin.android)
    id 'androidx.navigation.safeargs.kotlin'// Safe Args 插件,navigation中用来安全传递数据
}



导航图中添加参数:
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_graph"
    app:startDestination="@id/fragment_a">

    <!--label:fragment的标签
         layout:关联的布局
         name:关联的fragment-->
    <fragment
        android:id="@+id/fragment_a"
        android:name="com.byb.myphonevideo.ui.fragment.AFragment"
        android:label="Afragment"
        tools:layout="@layout/fragment_a">
        <!--destination:跳转的目的地 -->
        <action
            android:id="@+id/fragmentA_to_fragmentB"
            app:destination="@id/fragment_b" >
            <!--声明该动作需要传递的参数-->
            <argument
                android:name="key"
                android:defaultValue="初始值"
                app:argType="string"
                app:nullable="false" />
        </action>

    </fragment>

    <fragment
        android:id="@+id/fragment_b"
        android:label="BFragment"
        android:name="com.byb.myphonevideo.ui.fragment.BFragment"
        tools:layout="@layout/fragment_b">
        <!--声明接收的参数
       name:变量名
       defaultValue:默认值
       argType:变量的类型
       nullable:是否可以为空-->
        <argument
            android:name="key"
            android:defaultValue="初始值"
            app:argType="string"
            app:nullable="false" />
   </fragment>
</navigation>


fragment页面A:
class AFragment : Fragment(){
    private lateinit var textFragmentA: TextView
    private lateinit var btnFragmentA: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_a, container, false)
        initView(view)
        initListener()
        return view
    }
    private fun initView(view: View) {
        textFragmentA = view.findViewById(R.id.text_fragment_A)
        btnFragmentA = view.findViewById(R.id.btn_fragment_a)
    }

    private fun initListener() {
        btnFragmentA.setOnClickListener {
        //用rebuild后生成的文件AFragmentDirections来设置参数
           val navDestination = AFragmentDirections.fragmentAToFragmentB("传递的数据")
            //跳转
            findNavController().navigate(navDestination)
        }
    }
}



fragment页面B:
class BFragment : Fragment() {
    private lateinit var textFragmentB: TextView
    private lateinit var btnFragmentB: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_b, container, false)
        initView(view)
        initListener()
        return view
    }

    private fun initView(view: View) {
        textFragmentB = view.findViewById(R.id.text_fragment_b)
        btnFragmentB = view.findViewById(R.id.btn_fragment_b)
    }

    private fun initListener() {
        //获取传递过来的参数
        arguments?.let {
          textFragmentB.text = BFragmentArgs.fromBundle(it).key
        }
    }
}
  • 使用 Fragment Result API(AndroidX)
activity页面:(xml中放了两个并列的frame作为展示fragment的容器)
class MainActivity : AppCompatActivity() { //开启两个交互的fragment页面
    private lateinit var btnQueding: Button
    private lateinit var textMain: TextView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initView()
        initListener()
    }

    private fun initView() {
        btnQueding = findViewById(R.id.btn_tiaozhuan)
        textMain = findViewById(R.id.main_text)
    }

    private fun initListener() {
        btnQueding.setOnClickListener { //点击后开启fragment
            supportFragmentManager.beginTransaction()
                .add(R.id.frame_a, AFragment())
                .add(R.id.frame_b, BFragment())
                .commit()
        }
    }
}


fragment页面A:
class AFragment : Fragment() {
    private lateinit var textFragmentA: TextView
    private lateinit var btnFragmentA: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_a, container, false)
        initView(view)
        initListener()
        return view
    }
    private fun initView(view: View) {
        textFragmentA = view.findViewById(R.id.text_fragment_A)
        btnFragmentA = view.findViewById(R.id.btn_fragment_a)
    }
    private fun initListener() {
        btnFragmentA.setOnClickListener {
            //设置返回结果给目标
            setFragmentResult("key", bundleOf("name" to "小李"))
        }
    }
}


fragment页面B:
class BFragment : Fragment() {
    private lateinit var textFragmentB: TextView
    private lateinit var btnFragmentB: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_b, container, false)
        initView(view)
        initListener()
        return view
    }

    private fun initView(view: View) {
        textFragmentB = view.findViewById(R.id.text_fragment_b)
        btnFragmentB = view.findViewById(R.id.btn_fragment_b)
    }
    private fun initListener() {
        //通过监听获取数据的传递
        setFragmentResultListener("key"){requestKey, bundle ->
            textFragmentB.text = bundle.getString("name")
        }
    }
}
  • 共享 ViewModel(推荐)
添加实例化时需要的扩展函数的依赖:
implementation "androidx.activity:activity-ktx:1.8.1"
implementation "androidx.fragment:fragment-ktx:1.6.2"

viewmodel页面:
class SharedViewModel : ViewModel() {
    private val _data: MutableLiveData<Event<UserData>> = MutableLiveData<Event<UserData>>()
    val data: LiveData<Event<UserData>> = _data //只保留可读供外部调用
    fun sendDataFromFragment(data: UserData){
        _data.value = Event(data) //每次设置新数据都会创建新的实例,只有屏幕旋转等操作才会触发旧数据的重复接收
    }
}

/**
 * 包装器,防止配置更改等造成数据重复接收,解决数据倒灌
 */
class Event<T>(private val content: T) {

    private var hasBeenHandled = false
    fun getContentIfNotHandled(): T? {
        return if (hasBeenHandled) null
        else {
            hasBeenHandled = true
            content
        }
    }
}

/**
 * 数据类
 */
data class UserData(
    val type: String,
    val payload: Any?
)



activit页面:
class MainActivity : AppCompatActivity() {
    private lateinit var btnQueding: Button
    private lateinit var textMain: TextView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initView()
        initListener()
    }
    private fun initView() {
        btnQueding = findViewById(R.id.btn_tiaozhuan)
        textMain = findViewById(R.id.main_text)
    }
    private fun initListener() {
        btnQueding.setOnClickListener { //点击后开启fragment
            supportFragmentManager.beginTransaction()
                .add(R.id.frame_a, AFragment())
                .add(R.id.frame_b, BFragment())
                .commit()
        }
    }
}



fragment页面A:
class AFragment : Fragment() {
    private lateinit var textFragmentA: TextView
    private lateinit var btnFragmentA: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_a, container, false)
        initView(view)
        initListener()
        return view
    }
    private fun initView(view: View) {
        textFragmentA = view.findViewById(R.id.text_fragment_A)
        btnFragmentA = view.findViewById(R.id.btn_fragment_a)
    }
    //获取activity所在的view model的实例
    private val sharedViewModel : SharedViewModel by activityViewModels()
    private fun initListener() {
        btnFragmentA.setOnClickListener {
          sharedViewModel.sendDataFromFragment(UserData("12","小李"))
        }
    }
}


fragment页面B:
class BFragment : Fragment() {
    private lateinit var textFragmentB: TextView
    private lateinit var btnFragmentB: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_b, container, false)
        initView(view)
        initListener()
        return view
    }
    private fun initView(view: View) {
        textFragmentB = view.findViewById(R.id.text_fragment_b)
        btnFragmentB = view.findViewById(R.id.btn_fragment_b)
    }
   //用activityViewModels进行实例化,确保两个页面使用的都是父级activity所在的viewmodel
    private val sharedViewModel: SharedViewModel by activityViewModels()
    private fun initListener() {
         sharedViewModel.data.observe(viewLifecycleOwner){event ->
           textFragmentB.text = event?.getContentIfNotHandled()?.toString()
        }
    }
}
  • 使用EventBus
依赖:
implementation 'org.greenrobot:eventbus:3.3.1'


定义事件类:
data class DataBean1 (val id:Int,val name: String)//EventBus事件类
data class DataBean2 (val id:Int,val name: String)//此处也可以用一个类重复使用,接收时利用id不同来区分


activity页面:
class MainActivity : AppCompatActivity() {
    private lateinit var btnQueding: Button
    private lateinit var textMain: TextView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initView()
        initListener()
    }
    private fun initView() {
        btnQueding = findViewById(R.id.btn_tiaozhuan)
        textMain = findViewById(R.id.main_text)
    }
    private fun initListener() {
        btnQueding.setOnClickListener { //点击后开启fragment
            supportFragmentManager.beginTransaction()
                .add(R.id.frame_a, AFragment())
                .add(R.id.frame_b, BFragment())
                .commit()
        }
    }
}


fragment页面A:
class AFragment : Fragment() {
    private lateinit var textFragmentA: TextView
    private lateinit var btnFragmentA: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_a, container, false)
        initView(view)
        initListener()
        return view
    }
    private fun initView(view: View) {
        textFragmentA = view.findViewById(R.id.text_fragment_A)
        btnFragmentA = view.findViewById(R.id.btn_fragment_a)
    }

    override fun onStart() {
        super.onStart()
        EventBus.getDefault().register(this) //注册
    }

    override fun onStop() {
        super.onStop()
        EventBus.getDefault().unregister(this) //注销
    }
    /**
     * 设置事件处理方法
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun setData(data: DataBean2){
        //一个类重复使用时 if(data.id == 0) 
        textFragmentA.text = data.name
    }
    private fun initListener() {
        btnFragmentA.setOnClickListener {
            EventBus.getDefault().post(DataBean1(12,"小李"))
        }
    }
}



fragment页面B:
class BFragment : Fragment() {
    private lateinit var textFragmentB: TextView
    private lateinit var btnFragmentB: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_b, container, false)
        initView(view)
        initListener()
        return view
    }
    private fun initView(view: View) {
        textFragmentB = view.findViewById(R.id.text_fragment_b)
        btnFragmentB = view.findViewById(R.id.btn_fragment_b)
    }

    override fun onStart() {
        super.onStart()
        EventBus.getDefault().register(this) //注册
    }

    override fun onStop() {
        super.onStop()
        EventBus.getDefault().unregister(this) //注销
    }
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun setData(data: DataBean1){ //接收DataBean2类型的事件处理方法
        textFragmentB.text = data.toString()
    }
    private fun initListener() {
        btnFragmentB.setOnClickListener {
          EventBus.getDefault().post(DataBean2(122, "小李2"))
        }
    }
}

3.fragment跳转到子页面后数据返回时

  • 使用registerForActivityResult(只适合fragment跳转activity)
activity页面:
class MainActivity : AppCompatActivity() { //只开启一个fragment
    private lateinit var btnQueding: Button
    private lateinit var textMain: TextView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initView()
        initListener()
    }

    private fun initView() {
        btnQueding = findViewById(R.id.btn_tiaozhuan)
        textMain = findViewById(R.id.main_text)
    }

    private fun initListener() {
        btnQueding.setOnClickListener { //点击后开启fragment
            supportFragmentManager.beginTransaction()
                .add(R.id.frame_a, AFragment())
                .commit()
        }
    }
}


fragment跳转页:
class AFragment : Fragment() { 
    private lateinit var textFragmentA: TextView
    private lateinit var btnFragmentA: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_a, container, false)
        initView(view)
        initListener()
        return view
    }
    private fun initView(view: View) {
        textFragmentA = view.findViewById(R.id.text_fragment_A)
        btnFragmentA = view.findViewById(R.id.btn_fragment_a)
    }
    //通过监听获取数据
    private val startFragmentForResult =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            if (result.resultCode == Activity.RESULT_OK) {
                textFragmentA.text = result.data?.getStringExtra("keyFragment")
            }
        }

    private fun initListener() {
        btnFragmentA.setOnClickListener {
            startFragmentForResult.launch(Intent(requireContext(), BActivity::class.java).apply {
                putExtra("name", "fragment传递的数据")
            })
        }
    }
}


activity结束页:
class BActivity : AppCompatActivity() {

    private lateinit var btnTiaozhuan: Button
    private lateinit var textTest: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_b)
        initView()
        initData()
    }
    private fun initData() {
          //获取fragment传递过来的数据
        val data = intent.getStringExtra("name")
        textTest.text = data
        btnTiaozhuan.setOnClickListener {
            //设置该页面结束后返回的数据
           val intent = Intent().apply {
                 putExtra("keyFragment","activity返回的数据")
           }
            setResult(Activity.RESULT_OK,intent)
            finish()
        }
    }
    private fun initView() {
        textTest = findViewById(R.id.text_test)
        btnTiaozhuan = findViewById(R.id.btn_bactivity)
    }
}

  • 使用 Fragment Result API 的 requestKey
activity页面:
class MainActivity : AppCompatActivity() { //只开启一个父fragment
    private lateinit var btnQueding: Button
    private lateinit var textMain: TextView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initView()
        initListener()
    }
    private fun initView() {
        btnQueding = findViewById(R.id.btn_tiaozhuan)
        textMain = findViewById(R.id.main_text)
    }
    private fun initListener() {
        btnQueding.setOnClickListener { //点击后开启fragment
            supportFragmentManager.beginTransaction()
                .add(R.id.frame_a, AFragment())
                .commit()
        }
    }
}


fragment页面A:
class AFragment : Fragment() { //父fragment
    private lateinit var textFragmentA: TextView
    private lateinit var btnFragmentA: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_a, container, false)
        initView(view)
        initListener()
        return view
    }
    private fun initView(view: View) {
        textFragmentA = view.findViewById(R.id.text_fragment_A)
        btnFragmentA = view.findViewById(R.id.btn_fragment_a)
    }
    companion object{
        const val REQUEST_KEY_DETAIL = "0"
    }
    private fun initListener() {
        //设置监听获取数据
        setFragmentResultListener(REQUEST_KEY_DETAIL){requestKey, bundle ->
            if(requestKey == REQUEST_KEY_DETAIL )
                 textFragmentA.text = bundle.getString("name")
        }

        btnFragmentA.setOnClickListener {
            val fragment = BFragment().apply { //传递给子级fragment数据
                arguments = bundleOf("name" to "小李A")
            }
            //开启子fragment
            parentFragmentManager.beginTransaction().replace(R.id.frame_b, fragment)
                .addToBackStack(null)
                .commit()
        }
    }
}


fragment页面B:
class BFragment : Fragment() {
    private lateinit var textFragmentB: TextView
    private lateinit var btnFragmentB: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_b, container, false)
        initView(view)
        initListener()
        return view
    }

    private fun initView(view: View) {
        textFragmentB = view.findViewById(R.id.text_fragment_b)
        btnFragmentB = view.findViewById(R.id.btn_fragment_b)
    }

    private fun initListener() {
        //获取父fragment数据
        textFragmentB.text = arguments?.getString("name")
        btnFragmentB.setOnClickListener {
            //向父fragment传递数据后关闭自身
            setFragmentResult(AFragment.REQUEST_KEY_DETAIL, bundleOf("name" to "小李B"))
            parentFragmentManager.popBackStack() //commit时需要添加.addToBackStack(null)
        }
    }
  • 使用接口回调
activity页面:
class MainActivity : AppCompatActivity() { //只开启一个fragment
    private lateinit var btnQueding: Button
    private lateinit var textMain: TextView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initView()
        initListener()
    }

    private fun initView() {
        btnQueding = findViewById(R.id.btn_tiaozhuan)
        textMain = findViewById(R.id.main_text)
    }

    private fun initListener() {
        btnQueding.setOnClickListener { //点击后开启fragment
            supportFragmentManager.beginTransaction()
                .add(R.id.frame_a, AFragment())
                .commit()
        }
    }
}


fragment页面A:
class AFragment : Fragment(), DataInterfaceListener { //父fragment
    private lateinit var textFragmentA: TextView
    private lateinit var btnFragmentA: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_a, container, false)
        initView(view)
        initListener()
        return view
    }
    private fun initView(view: View) {
        textFragmentA = view.findViewById(R.id.text_fragment_A)
        btnFragmentA = view.findViewById(R.id.btn_fragment_a)
    }
    private fun initListener() {
        btnFragmentA.setOnClickListener {
            //给子fragment里面的接口实例化
            val fargment = BFragment().apply {
                setDataInterfaceListener(this@AFragment)
            }
            //跳转子fragment
            parentFragmentManager.beginTransaction()
                .add(R.id.frame_b, fargment)
                .addToBackStack(null) //添加到栈里管理,方便子页面跳转后出栈
                .commit()
        }
    }
    /**
     * 重写接口的方法来获取数据
     */
    override fun dataUpdate(data: String) {
        textFragmentA.text = data
    }
}



fragment页面B:
class BFragment : Fragment() {
    private lateinit var textFragmentB: TextView
    private lateinit var btnFragmentB: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_b, container, false)
        initView(view)
        initListener()
        return view
    }
    private fun initView(view: View) {
        textFragmentB = view.findViewById(R.id.text_fragment_b)
        btnFragmentB = view.findViewById(R.id.btn_fragment_b)
    }
    //声明接口实例
    private var dataInterfaceListener: DataInterfaceListener? = null
    fun setDataInterfaceListener(dadataInterfaceListenerta: DataInterfaceListener) {
        //通过AFragment来进行实例化
        this.dataInterfaceListener = dadataInterfaceListenerta
    }
    private fun initListener() {
        btnFragmentB.setOnClickListener {
            dataInterfaceListener?.dataUpdate("fragmentB传递的数据")
            parentFragmentManager.popBackStack()
        }
    }
}
  • 使用ViewModel
添加实例化时需要的扩展函数的依赖:
implementation "androidx.activity:activity-ktx:1.8.1"
implementation "androidx.fragment:fragment-ktx:1.6.2"


viewmodel页面:
class SharedViewModel : ViewModel() {
    private val _data: MutableLiveData<Event<UserData>> = MutableLiveData<Event<UserData>>()
    val data: LiveData<Event<UserData>> = _data //只保留可读供外部调用
    fun sendDataFromFragment(data: UserData){
        _data.value = Event(data) //每次设置新数据都会创建新的实例,只有屏幕旋转等操作才会触发旧数据的重复接收
    }
}

/**
 * 包装器,防止配置更改等造成数据重复接收,解决数据倒灌
 */
class Event<T>(private val content: T) {

    private var hasBeenHandled = false
    fun getContentIfNotHandled(): T? {
        return if (hasBeenHandled) null
        else {
            hasBeenHandled = true
            content
        }
    }
}

/**
 * 数据类
 */
data class UserData(
    val type: String,
    val payload: Any?
)


activity页面:
class MainActivity : AppCompatActivity() { //只开启一个fragment
    private lateinit var btnQueding: Button
    private lateinit var textMain: TextView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initView()
        initListener()
    }
    private fun initView() {
        btnQueding = findViewById(R.id.btn_tiaozhuan)
        textMain = findViewById(R.id.main_text)
    }
    private fun initListener() {
        btnQueding.setOnClickListener { //点击后开启fragment
            supportFragmentManager.beginTransaction()
                .add(R.id.frame_a, AFragment())
                .commit()
        }
    }
}


fragment页面A:
class AFragment : Fragment(){ 
    private lateinit var textFragmentA: TextView
    private lateinit var btnFragmentA: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_a, container, false)
        initView(view)
        initListener()
        return view
    }
    private fun initView(view: View) {
        textFragmentA = view.findViewById(R.id.text_fragment_A)
        btnFragmentA = view.findViewById(R.id.btn_fragment_a)
    }
    //初始化   注意此处的activityViewModels表明使用的是activity级别
    private val sharedViewModel: SharedViewModel by activityViewModels()
    private fun initListener() {
          //监听
        sharedViewModel.data.observe(viewLifecycleOwner){ event ->
            if (event != null){
              val data =  event.getContentIfNotHandled()
                textFragmentA.text = data.toString()
            }
        }
        btnFragmentA.setOnClickListener {
            //跳转
                parentFragmentManager.beginTransaction().add(R.id.frame_b, BFragment())
                    .addToBackStack(null)
                    .commit()
        }
    }
}



fragment页面B:
class BFragment : Fragment() {
    private lateinit var textFragmentB: TextView
    private lateinit var btnFragmentB: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_b, container, false)
        initView(view)
        initListener()
        return view
    }
    private fun initView(view: View) {
        textFragmentB = view.findViewById(R.id.text_fragment_b)
        btnFragmentB = view.findViewById(R.id.btn_fragment_b)
    }
    // 注意此处的activityViewModels表明使用的是activity级别
    private val sharedViewModel: SharedViewModel by activityViewModels()
    private fun initListener() {
        btnFragmentB.setOnClickListener {
             sharedViewModel.sendDataFromFragment(UserData("12","小李"))
            parentFragmentManager.popBackStack()//出栈
        }
    }
}
  • 使用EventBus
依赖:
implementation 'org.greenrobot:eventbus:3.3.1'


定义事件类:
data class DataBean (val id:Int,val name: String)//EventBus事件类

fragment页面A:(activity页面只开启了该fragment,同上)
class AFragment : Fragment() {
    private lateinit var textFragmentA: TextView
    private lateinit var btnFragmentA: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_a, container, false)
        initView(view)
        initListener()
        return view
    }

    private fun initView(view: View) {
        textFragmentA = view.findViewById(R.id.text_fragment_A)
        btnFragmentA = view.findViewById(R.id.btn_fragment_a)
    }

    override fun onStart() {
        super.onStart()
        EventBus.getDefault().register(this) //注册
    }

    override fun onStop() {
        super.onStop()
        EventBus.getDefault().unregister(this) //注销
    }
    /**
     * 设置事件处理方法
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun setData(data: DataBean){
        textFragmentA.text = data.name
    }
    private fun initListener() {
        btnFragmentA.setOnClickListener {
            //跳转
            parentFragmentManager.beginTransaction().add(R.id.frame_b, BFragment())
                .addToBackStack(null)
                .commit()
        }
    }
}


fragment页面B:
class BFragment : Fragment() {
    private lateinit var textFragmentB: TextView
    private lateinit var btnFragmentB: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_b, container, false)
        initView(view)
        initListener()
        return view
    }
    private fun initView(view: View) {
        textFragmentB = view.findViewById(R.id.text_fragment_b)
        btnFragmentB = view.findViewById(R.id.btn_fragment_b)
    }
    private fun initListener() {
        btnFragmentB.setOnClickListener {
          EventBus.getDefault().post(DataBean(12,"小李"))
            parentFragmentManager.popBackStack()//出栈
        }
    }
}
  • 使用navigation框架传递数据
导航图:
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_graph"
    app:startDestination="@id/fragment_a">
    <!--label:fragment的标签
         layout:关联的布局
         name:关联的fragment-->
    <fragment
        android:id="@+id/fragment_a"
        android:name="com.byb.myphonevideo.ui.fragment.AFragment"
        android:label="Afragment"
        tools:layout="@layout/fragment_a">
        <!--id:用于标识动作
        destination:跳转的目的地 -->
        <action
            android:id="@+id/fragmentA_to_fragmentB"
            app:destination="@id/fragment_b" />
    </fragment>
    <fragment
        android:id="@+id/fragment_b"
        android:name="com.byb.myphonevideo.ui.fragment.BFragment"
        android:label="BFragment"
        tools:layout="@layout/fragment_b">
    </fragment>
</navigation>



activity页面xml:(代码端不需要关于fragment的额外操作)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".ui.MainActivity">

    <!--navigation中添加NavHostFragment控件作为导航宿主
     name:此处为默认实现,也可使用自定以的fragment,但必须实现NavHost或继承NavHostFragment
     navGrap:将当前的导航宿主与导航图相关联
     defaultNavHost:是否由导航宿主拦截返回事件,true时则返回键按下不会直接推出附加的activity
     -->
    <fragment
        android:id="@+id/fragment_nav"
        android:layout_width="match_parent"
        android:layout_height="500dp"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:defaultNavHost="true"
        app:navGraph="@navigation/nav_graph"
        />
    <Button
        android:id="@+id/btn_tiaozhuan"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="@string/btn_text" />

    <TextView
        android:id="@+id/main_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="30dp"
        android:text="@string/app_name" />
</LinearLayout>


fragment页面A:
class AFragment : Fragment() {
    private lateinit var textFragmentA: TextView
    private lateinit var btnFragmentA: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_a, container, false)
        initView(view)
        initListener()
        return view
    }
    private fun initView(view: View) {
        textFragmentA = view.findViewById(R.id.text_fragment_A)
        btnFragmentA = view.findViewById(R.id.btn_fragment_a)
    }
    private fun initListener() {
        //注册结果监听器  currentBackStackEntry拿到当前页面在返回栈中的entry,获取到savedStateHandle中livedata来获取最新值
        findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<String>("key")
            ?.observe(viewLifecycleOwner) { result ->
                textFragmentA.text = result //获取到数据后绑定在控件上显示
            }
        btnFragmentA.setOnClickListener {
            //使用Safe Args来进行跳转
           val navDestination = AFragmentDirections.fragmentAToFragmentB()
            findNavController().navigate(navDestination)
        }
    }
}



fragment页面B:
class BFragment : Fragment() {
    private lateinit var textFragmentB: TextView
    private lateinit var btnFragmentB: Button
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_b, container, false)
        initView(view)
        initListener()
        return view
    }
    private fun initView(view: View) {
        textFragmentB = view.findViewById(R.id.text_fragment_b)
        btnFragmentB = view.findViewById(R.id.btn_fragment_b)
    }
    private fun initListener() {
        btnFragmentB.setOnClickListener {
            //获取到导航栈里面前一个条目,也就是跳转到该页面的AFragment
            val previousBackStackEntry = findNavController().previousBackStackEntry
             //获取到导航栈栈顶的条目即当前BFragment
            //val current = findNavController().currentBackStackEntry
             //将数据存储到A页面的savedStateHandle
            previousBackStackEntry?.savedStateHandle?.set("key","小李")
            //弹出栈
            findNavController().popBackStack()
        }
    }
}

navigation详细使用教程可参考:https://blog.csdn.net/lmy19940716/article/details/113465700?ops_request_misc=&request_id=&biz_id=102&utm_term=navigation%E4%BC%A0%E9%80%92fragment%E4%B9%8B%E9%97%B4%E7%9A%84%E6%95%B0%E5%80%BC&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-1-113465700.142v102pc_search_result_base6&spm=1018.2226.3001.4187

后续持续更新详细方案内容…

Logo

为武汉地区的开发者提供学习、交流和合作的平台。社区聚集了众多技术爱好者和专业人士,涵盖了多个领域,包括人工智能、大数据、云计算、区块链等。社区定期举办技术分享、培训和活动,为开发者提供更多的学习和交流机会。

更多推荐