Intent和Bundle传值上的区别?
假设数据需要从A页面传到B页面再传到C页面
Intent
A页面
Intent intent=new Intent(MainActivity.this,BActivity.class);
intent.putExtra("String","MainActivity中的值");
intent.putExtra("int",11);
startActivity(intent);
B页面
Intent intent = getIntent();
String string = intent.getStringExtra("String");
Int key = intent.getIntExtra("int",0);
Intent intent=new Intent(BActivity.this,CActivity.class);
intent.putExtra("String1",string);
intent.putExtra("int1",key);
intent.putExtra("boolean",true);
startActivity(intent);
C页面
Intent intent4=getIntent();//获取上一个页面的意图
String data4=intent4.getStringExtra("String");//通过名字获取上一个页面传递的数据
Int key4 = intent.getIntExtra("int",0);
Boolean bool=intent.getBooleanExtra("boolean",true);
可以看到,使用的时候不方便的地方是需要在B页面将数据一条条取出来然后再一条条传输给C页面。而使用Bundle的话,在B页面可以直接取出传输的Bundle对象然后传输给C页面。
Bundle
A页面中
Intent intent = new Intent(MainActivity.this, BActivity.class);
Bundle bundle = new Bundle();
bundle.putString("String","MainActivity中的值");
bundle.putInt("int",11);
intent.putExtra("bundle",bundle);
startActivity(intent);
B页面中
//接受数据
Intent intent = getIntent();
Bundle bundle=intent.getBundleExtra("bundle");
//发送数据
Intent intent=new Intent(BActivity.this,CActivity.class);
//可以传给CActivity额外的值
bundle.putBoolean("boolean",true);
intent.putExtra("bundle1",bundle);
startActivity(intent);
Bundle 可通过上一个页面getIntent().getBundleExtra(“上个页面的key”),来取到上个页面的数据,当前页面需要其他数据时,只需在当前页面继续加即可。而Intent想要获取数据的话,每次都要 Intent intent = getIntent(); String string = intent.getStringExtra(“String”);Int key = intent.getIntExtra(“int”,0);这样会比较麻烦
Bundle可对对象进行操作,而Intent是不可以。Bundle相对于Intent拥有更多的接口,用起来比较灵活,但是使用Bundle也还是需要借助Intent才可以完成数据传递总之,Bundle旨在存储数据,而Intent旨在传值。
第二张图,有细节写错,是通过setResult()方法传递数据给MainActivity
package com.example.getbackdata;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
public final static int REQUST_CODE=1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void firstbutton(View view) {
//步骤一:
Intent intent=new Intent(this,otherActivity.class);
startActivityForResult(intent,REQUST_CODE);
}
//因为我们是使用startActivity来启动otherActivity的,所以当otherActivity被finish()销毁
// 后,他会自动回调MainActivity中的onActivityResult方法。而otherActivity也通过setResult()方
//法将数据传递到了MainActivity,此时我们在MainActivity中设置onActivityResult方法来接收
//返回的数据
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode)
{
case REQUST_CODE:
if(resultCode==0) {
TextView mainText = (TextView) findViewById(R.id.mainText);
mainText.setText(data.getStringExtra("result"));
}
//data携带返回数据的intent
break;
default:
}
}
}
因为我们是使用startActivity来启动otherActivity的,所以当otherActivity被finish()销毁 后,他会自动回调MainActivity(上一个活动)中的onActivityResult方法。而otherActivity也通过setResult()方法将数据传递到了MainActivity,此时我们在MainActivity中设置onActivityResult方法来接收
otherActivity
package com.example.getbackdata;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
public class otherActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_other);
}
public void button2(View view) {
//步骤二
EditText otheredit = (EditText) findViewById(R.id.otheredit);
Intent intent=new Intent();//
intent.putExtra("result",otheredit.getText().toString());
this.setResult(0,intent);
//通过setResult传递数据给MainActivity
//setResult两个参数(第一个是:请求码,第二个是将带有数据的intent传递到MainActivity)
finish();
}
}
请求码是用来区分打开activity的是哪一个按钮,结果码是用来区分当前传回的数据来自于哪一个activity。
父Activity也就是 startActivityForResult所在的Activity,子Activity是 setResult所在的Activity
从子Activity获取返回结果
public void startActivityForResult(Intent intent, int requestCode)
该方法的第一个参数是intent,第二个参数是请求代码。请求代码先发送给子activity,然后再返回给父activity的用户定义整数值。当一个activity启动多个不同类型的子activity,且需要判断区分消息回馈方时,通常会用到该请求代码
设置返回结果
public final void setResult(int resultCode)
public final void setResult(int resultCode,Intent data)
一般来说,参数resultCode可以是以下两个预定义常量中的任何一个
Activity.RESULT_OK
Activity.RESULT_CANCELED
新建一个BaseActivity继承自AppCompatActivity,并重写onCreate()方法
open class BaseActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d("BaseActivity", javaClass.simpleName)
}
}
我们在onCreate()方法中加了一行日志,用于打印当前实例的类名。Kotlin中的BaseActivity::class.java表示获取BaseActivity类的class对象,相当于在Java中调用BaseActivity.class。在上述代码中,我们先获取了当前实例的Class对象,然后再调用simpleName获取当前实例的类名。
接下来我们同样让Activity继承BaseActivity。为了使得BaseActivity可以被继承已经在类名的前面加上open关键字。
这样每当我们进入一个Activity界面,该Activity的类名就会被打印出来,这样我们就能知晓当前界面对应哪一个Activity了。
如果你的手机界面还停留在ThirdActivity,你会发现当前退出程序是非常不方便的,需要连按3次Back键才行。如果我们的程序需要注销或者退出的功能怎么办呢?就需要一个能随时随地都能退出程序的方案才行。
解决方法就是用一个专门的集合来对所有的Activity进行管理就可以了。
object ActivityCollector {
private val activities=ArrayList<Activity>()
fun addActivity(activity: Activity){
activities.add(activity)
}
fun removeActivity(activity: Activity){
activities.remove(activity)
}
fun finishAll(){
for(activity in activities){
if(!activity.isFinishing){
activity.finish()
}
}
activities.clear()
}
}
这里使用单例类,是因为全局只需要一个Activity集合。在集合中,我们通过一个ArrayList来暂存Activity,,然后提供了一个addActivity()方法,用于向ArrayList中添加Activity;提供了一个removeActivity()方法,用于从ArrayList中移除Activity;最后提供一个finishAll()方法,用于将ArrayList中存储的Activity全部销毁。注意在销毁之前我们还需要先调用activity.isFinishing来判断Activity是否正在销毁中,因为Activity还可能通过按下Back键等方式被销毁,如果该Activity没有正在销毁中,我们再去调用他的finish()方法来销毁他。
open class BaseActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d("BaseActivity", javaClass.simpleName)
ActivityCollector.addActivity(this)
}
override fun onDestroy() {
super.onDestroy()
ActivityCollector.removeActivity(this)
}
}
在BaseActivity的onCreate()方法调用了ActivityCollector的addActivity()方法,表明将当前正在创建的Activity添加到集合里。然后在BaseActivity中重写onDestroy()方法,并调用ActivityCollector的removeActivity()方法,表明从集合里移除一个马上要销毁的Activity。
所以当你想要在什么地方退出程序,只需要调用ActivityCollector.finishAll()方法就可以了。
假设有一个SecondActivity中需要用到两个非常重要的字符串参数,在启动SecondActivity的时候必须传递过来,我们很容易写出如下代码
var intent=Intent(this,SecondActivity::class.java)
intent.putExtra("param1","data1")
intent.putExtra("param2","data2")
startActivity(intent)
虽然这样写是正确的,但是当我们不清楚启动SecondActivity需要传递哪些数据的时候,会很麻烦,这个时候我们可以换一种写法。
companion object{
fun actionStart(context: Context, data1:String, data2:String){
val intent=Intent(context,SecondActivity::class.java)
intent.putExtra("param1",data1)
intent.putExtra("param2",data2)
context.startActivity(intent)
}
}
我们使用 companion object的语法结构,并在compainion object中定义一个actionStart()方法,之所以这么写,是因为Kotlin规定,所有定义在compainion object中的方法都可以使用类似于Java静态方法的形式调用。在actionStart()方法中完成了对Intent的构建,另外所有SecondActivity中需要的数据都通过actionStart()方法的参数传递过来的,然后把它们存储到Intent中,最好调用startActivity()方法启动SecondActivity。
这样写的好处就是一目了然,SecondActivity中需要的数据在方法中全部体现出来了,另外还简化了启动Activity的代码,只需要一行即可
button.setOnClickListener {
SecondActivity.actionStart(this,"data1","data2")
}