activity与fragment的传参记录
文章目录
前言
本文主要记录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
后续持续更新详细方案内容…
为武汉地区的开发者提供学习、交流和合作的平台。社区聚集了众多技术爱好者和专业人士,涵盖了多个领域,包括人工智能、大数据、云计算、区块链等。社区定期举办技术分享、培训和活动,为开发者提供更多的学习和交流机会。
更多推荐




所有评论(0)