1、activity –> activity 数据传递
两个activity,Activity a启动Activity b
方法1:Intent传递数据
可以使用 startActivity(Intent intent)方法来传入一个Intent对象。在这个Intent对象中指定activity是从a跳转到b,(也可以通过Intent对象来指定要完成的action操作),同时可以通过intent对象携带数据传递给b。在activity b中通过intent获取传递过来的数据。示例代码如下:
activity a中:
var intent= Intent(this,bActivity::class.java)
intent.putExtra("msg","测试")
//或者
var bundle = Bundle()
bundle.putString("msg", "测试")
intent.putExtra("bun", bundle)
startActivity(intent)
activity b中:
var msg = this.intent.getStringExtra("msg")
方法2:SharedPreferences传递数据 (SQLite、Content Provider和File也可以传递数据,数据持久化)
SharedPreferences类是Android平台轻量级的存储类,用来保存应用的一些常用配置,比如Activity状态,Activity暂停时,将此activity的状态保存到SharedPereferences中;当Activity重载,系统回调方法onSaveInstanceState时,再从SharedPreferences中将值取出。SharedPreferences保存的数据会以键值对的形式保存到安卓系统文件/data/data/包名/shared_prefs目录下的xml文件。示例代码如下:
activity a 中:
var sp = this.getSharedPreferences("info", Context.MODE_PRIVATE)
//获取sp编辑器
var edit = sp.edit()
edit.putString("msg", "测试")
edit.commit()
var intent = new Intent(this,bActivity::class.java)
startActivity(intent)
activity b 中:
var sp = getSharedPreferences("info", Context.MODE_PRIVATE)
var value = sp.getString("msg","Null")
方法3:静态变量传递数据
在被启动的类中定义静态变量并赋值,示例代码如下:
activity a中:
bActivity.msg="测试"
var intent = new Intent(this,bActivity::class.java)
startActivity(intent)
activity b中:
companion object{
var msg:String?=null
}
方法4:使用全局变量传递数据
定义一个继承自Application的类,这个类中的变量即为全局变量,有全局的生命周期。示例代码如下:
Application自定义类:
class MyApp:Application(){
private var msg:String?=null
fun setMsg(msg:String){
this.msg=msg
}
fun getMsg():String?{
return this.msg
}
}
activity a中:
var app = this.application as MyApp
app.setMsg("测试")
var intent = new Intent(this,bActivity::class.java)
startActivity(intent)
activity b中:
var app = this.application as MyApp
var msg = app.getMsg()
方法5:使用系统粘贴板传递数据
activity a中:
var clipboardManager = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
var description = ClipDescription("来自用户的输入", arrayOf(ClipDescription.MIMETYPE_TEXT_PLAIN))
var clipData = ClipData(description,ClipData.Item("测试"))
clipboardManager.primaryClip = clipData
var intent = new Intent(this,bActivity::class.java)
startActivity(intent)
activity b中:
var clipboardManager = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
var clipData = clipboardManager.primaryClip
var clipText = ""
if(clipData.itemCount>0){
clipText=clipData.getItemAt(0).text.toString()
}
2、activity –> activity 数据回传
通过调用startActivity(Intent intent)方法实现返回跳转的,依旧可以使用以上5种方法实现。
这里的数据回传是指,不通过调用startActivity(Intent intent)方法跳转,而是调用调用finish()方法结束被启动activity b的生命周期,而重新返回到activity a。具体细节见如下示例代码:
activity a中:
class QuestionActivity : AppCompatActivity() {
private lateinit var etNumA:EditText
private lateinit var etNumB:EditText
private lateinit var tvResult:TextView
private lateinit var btnCompute:Button
private var numA:Int?= null
private var numB:Int?= null
private val REQUEST_CODE = 1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_question)
this.title = "activity a"
//获取控件
etNumA = findViewById(R.id.et_num_a)
etNumB = findViewById(R.id.et_num_b)
tvResult = findViewById(R.id.tv_num_result)
btnCompute = findViewById(R.id.btn_num_compute)
btnCompute.setOnClickListener {
//获取文本值
numA = etNumA?.text?.toString()?.toInt()
numB = etNumB?.text?.toString()?.toInt()
var intent = Intent(this@QuestionActivity,AnswerActivity::class.java)
intent.putExtra("numA",numA)
intent.putExtra("numB",numB)
/*
* 注意点1:必须是调用startActivityForResult方法(不是startActivity方法)。
* 这个方法的用意是被启动activity生命周期结束时,通过一些操作会把数据传递给启动activity。
* 启动activity通过onActivityResult来接收数据。
*/
this@QuestionActivity.startActivityForResult(intent,REQUEST_CODE)
}
}
/*
* 注意点2:
* 接收从Activity b回传的数据
* 启动activity通过onActivityResult来接收数据,所以需要重写对回传的数据进行处理
*/
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if(resultCode== 2 && requestCode == REQUEST_CODE){
tvResult.text = data?.getIntExtra("result",0).toString()
}
}
}
activity b中:
class AnswerActivity : AppCompatActivity() {
private lateinit var tvNumA: TextView
private lateinit var tvNumB: TextView
private lateinit var etResult: EditText
private lateinit var btnReturnResult: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_answer)
this.title = "activity b"
//获取控件
tvNumA = findViewById(R.id.tv_num_a)
tvNumB = findViewById(R.id.tv_num_b)
etResult = findViewById(R.id.et_num_result)
btnReturnResult = findViewById(R.id.btn_num_result)
//获取值
var numA = intent.getIntExtra("numA",0)
var numB = intent.getIntExtra("numB",0)
//设置值
tvNumA.text = numA?.toString()
tvNumB.text = numB?.toString()
btnReturnResult.setOnClickListener {
var result = etResult.text.toString().toInt()
var intent = Intent()
var bundle= Bundle()
bundle.putInt("result",result)
intent.putExtras(bundle)
/*
* 注意点3:必须调用这个方法,把这个意图设置为返回结果,当此Activity生命周期结束时会把这个意图作为响应返回
*/
this.setResult(2,intent)
/*
* 注意点4:结束当前Activity生命周期,结合setResult()方法实现数据回传
*/
this.finish()
}
}
}
3、activity –> fragment 数据传递
方法1:arguments传递数据
示例代码如下:
activity中:
var bundle = Bundle()
bundle.putString("title","我是来自activity的信息1111")
var fragment = Fragment05()
fragment.arguments = bundle
fragmentManager.beginTransaction().add(R.id.fragment_activity_interactive_f5,fragment).commit()
fragment中:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
var view = inflater?.inflate(R.layout.fragment05, container, false)
var titleTV=view.findViewById<TextView>(R.id.fragment_activity_interactive_title5)
//从arguments中获取数据
titleTV.text = arguments.getString("title")
return view
}
方法2:构建返回Fragment对象的静态方法传递数据
activity中:
fragmentManager.beginTransaction()
.add(R.id.fragment_activity_interactive_f7,Fragment07.getInstance("我是来自activity的信息3333"))
.commit()
fragment中:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
//引用创建好的xml布局
var view = inflater?.inflate(R.layout.fragment07, container, false)
var titleTV=view.findViewById<TextView>(R.id.fragment_activity_interactive_title7)
titleTV.text = arguments?.getString("title")
return view
}
companion object {
fun getInstance(msg:String):Fragment07{
var fragment = Fragment07()
var bundle = Bundle()
bundle.putString("title",msg)
fragment.arguments = bundle
return fragment
}
}
其本质还是通过arguments传递数据。
方法3:activity中创建方法传递数据
与activity绑定的所有fragment都可以轻松获取到activity对象实例,通过在activity中构建方法可以很方便传递数据。示例代码如下:
activiy中:
fragmentManager.beginTransaction().add(R.id.fragment_activity_interactive_f6,Fragment06()).commit()
fun getMsg():String{
return "我是来自activity的信息2222"
}
fragment中:
var msg = (activity as MainActivity)?.getMsg()
4、fragment –> activity 数据回传
方法1:回调接口传递数据
fragment定义回调接口,activity实现回调接口,通过这种方式实现fragment向activity回传数据。
示例场景是fragment视图中有一个button按钮,点击按钮向activity传递数据。示例代码代码如下:
fragment中:
class Fragment08 : Fragment(),View.OnClickListener{
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
var view = inflater?.inflate(R.layout.fragment08, container, false)
return view
}
override fun onResume() {
super.onResume()
this.view.findViewById<Button>(R.id.fragment_activity_interactive_fa1).setOnClickListener(this)
}
override fun onClick(v: View?) {
println("2================${activity}===============")
if(this.activity!=null){
/*
* 注意点2:activity调用实现了的回调接口的方法,实现在fragment中向activity传递数据
*/
(activity as FragmentMain6Activity).process("我是来自fragment的信息aaaa")
}
}
/*
* 注意点1:回调接口,供activity实现
*/
interface Fragment07Interface{
fun process(msg:String)
}
}
activity中:
class MainActivity : AppCompatActivity(), Fragment08.Fragment07Interface{
override fun process(msg: String) {
var view = findViewById<TextView>(R.id.fragment_activity_interactive_f8)
view.text = msg
}
}
5、fragment –> fragment 数据传递与数据回传
5.1 同个container不同fragment之间数据传递
方法1:activity中定义方法
不同fragment通过获取到的activity对象操作这个方法,实现传递数据。
方法2:同样可以通过arguments传递数据
方法3:被传递数据的frament定义返回fragment对象的静态方法
companion object {
fun getInstance(msg:String):Fragment07{
var fragment = Fragment07()
var bundle = Bundle()
bundle.putString("title",msg)
fragment.arguments = bundle
return fragment
}
}
通过定义类似示例方法,然后调用该方法实现数据传递。也可以定义别的类似方法。
方法4:同样可以通过类似上面的回调接口传递数据。
原理类似fragment向activity回传数据,fragment a定义回调接口,activity实现回调接口,fragment a把数据传递给activity,fragment b从activity中获取数据。
方法5:开源框架EventBus发布订阅模式传递数据
看官方demo
5.2 同个container不同fragment之间数据回传
一个fragment生命周期结束时把数据回传给目标fragment。
注意三点:
- 在启动到另一个fragment之前调用setTargetFragment方法指定要把数据回传到的目标fragment
示例代码如下:
var fragment10 = Fragment10()
//设置目标fragment,并设置请求码
fragment10.setTargetFragment(this@Fragment09, REQUEST_CODE)
fragmentManager.beginTransaction().hide(this).add(R.id.activity_container_2fragment_container,fragment10,"fragment10").addToBackStack(null).commit()
- 目标fragment重写onActivityResult方法,实现接收另一个fragment回传过来的数据
示例代码如下,目标fragment:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if(resultCode == RESULT_OK && data!=null){
if (requestCode == REQUEST_CODE){
view.findViewById<TextView>(R.id.activity_container_fragment1_msg).text = data.getStringExtra("msg")
view.findViewById<ImageView>(R.id.activity_container_fragment1_image).setImageResource(data.getIntExtra("image",0))
}
}
}
- 另一个fragment生命周期结束时,调用目标fragment方法onActivityResult,把数据回传给目标fragment
示例代码如下:
var fragment9 = Fragment09()
var intent = Intent()
var bundle=Bundle()
bundle.putInt("image",image)
bundle.putString("msg","这是一张图片")
intent.putExtras(bundle)
//调用方法,回传数据给目标fragment
this.targetFragment.onActivityResult(Fragment09.REQUEST_CODE,Activity.RESULT_OK,intent)
//当前fragment出栈,生命周期结束
fragmentManager.popBackStack()
5.3 同个activity不同container的fragment之间数据传递
由于讨论的是不同container中的fragment,所以一般出现在同一个布局中,所处的生命周期一致。直接获取两个fragment中控件进行数据操作即可。
[完整demo]
参考资料:
2、关于Android Activity之间传递数据的6种方式
3、老罗安卓开发
4、Activity之间数据传递(一)(简单传递,数据包Bundle,传递对象)
6、Android 基础:Fragment,看这篇就够了 (上)
7、Fragment之间传递参数和Fragment返回上一个Fragment传回数据