一、Activity的启动
1、什么是Intent?
Intent:直译为意图,通俗来说就是你想要做什么或想要去哪?
作用:Intent是Activity、Service和BroadCastReceiver这三个应用组件进行通信的信使。
例如:想要从FirstActivity启动另外一个SecondActivity,就必须使用Intent对象了。
(1)无结果的页面跳转
@Override
public void onClick(View v) {
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
**startActivity(intent);**
}
(2)有结果的页面跳转
Activity A跳转到Activity B
public static final int REQUEST_SEARCH = 100;
Intent intent = new Intent(getActivity(), MapSearchDeviceActivity.class);
startActivityForResult(intent, REQUEST_SEARCH);
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {//判断是否返回成功
if (requestCode == REQUEST_SEARCH) {//判断来自哪个Activity
jd = Float.parseFloat(data.getStringExtra("jd"));
wd = Float.parseFloat(data.getStringExtra("wd"));
}
}
}
Activity B
Intent intent = new Intent();
intent.putExtra("jd", dataBeanList.get(position).getJd());
intent.putExtra("wd", dataBeanList.get(position).getWd());
MapSearchDeviceActivity.this.setResult(RESULT_OK, intent);
MapSearchDeviceActivity.this.finish();
当结果码为RESULT_OK,且请求码为100时,Activity A获取Activity B传过来的intent值。
2、什么是intentFilter?
IntentFilter:意图过滤器,主要用来过滤隐式意图,当用户进行一项操作的时候,Android系统会根据配置的 “意图过滤器” 来寻找可以响应该操作的组件,服务。
作用: IntentFilter通常是定义在AndroidManifest.xml文件中,也可以动态设置,通常是用来声明组件想要接受哪种Intent。例如,你如果为一个Activity设置了IntentFilter,你就可以在应用内或者其他应用中,用特定的隐式Intent来启动这个Activity,如果没有为Activity设置IntentFilter,那么你就只能通过显示Intent来启动这个Activity。
3、显式Intent与隐式Intent的区别
显式Intent:明确指定目标组件的意图 Intent intent=new Intent(Context context,Class clazz); 当操作当前自己的应用组件时使用。
隐式Intent:没有明确指定目标组件的意图,Intent(String action)当操作其他应用组件时使用
ep:打电话和发短信 都是用的隐式意图。
Intent intentA=new Intent(Intent.ACTION_DIAL);
//获取号码
String number=et_main_number.getText().toString().trim();
//携带号码
Uri uri = Uri.parse("**tel:**"+number); //tel是个约束
intent.setData(uri);
//需要启动另外一个应用:需要使用隐式意图
startActivity(intent);
Intent intentB = new Intent(Intent.ACTION_SENDTO);
//发短信要有号码,所以获取电话号码,携带着电话号码,再去编辑短信
//获取号码
String number = et_main_number.getText().toString().trim();
Uri uri=Uri.parse("**sms:**"+number);
//携带号码
intent.setData(uri);
//获取短信
String content = et_main_content.getText().toString();
//携带短信
intent.putExtra("**sms_body**", content);
//启动到另外一个短信界面,需要隐式意图
startActivity(intent);
3、PendingIntent详解
PendingIntent是一种特殊的Intent,和Intent的区别在于Intent是立刻执行的,而PendingIntent不是,可以被理解为一种异步处理机制。
作用:PendingIntent执行的操作实质上是参数传进来的Intent操作,像通知栏消息的发送就是使用PendingIntent实现。
Intent intent = new Intent(action);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
为了提升应用的安全性,Android12要求应用创建的每个PendingIntent对象都要指定可变性, 使用PendingIntent.FLAG_MUTABLE 或PendingIntent.FLAG_IMMUTABLE标志。
如果不设置任一可变性标志, 系统将会抛出IllegalArgumentException异常,报错内容如下:
java.lang.IllegalArgumentException: XXX: Targeting S+ (version 31 and above)
requires that one of FLAG_IMMUTABLE or FLAG_MUTABLE be specified when
creating a PendingIntent.
二、Activity的关闭与销毁
1、调用finish()方法,用于关闭当前的Activity
2、finish()方法与onDestroy()方法的区别?
finish()属于执行方法,而destroy()属于系统方法。finish()是在程序执行的过程中使用它来将对象销毁,而destroy()方法是在系统将该activity完全销毁(从内存中移除),释放资源空间。在写程序过程中,一般调用finish()。如果我们希望系统释放资源的时候,进行某些操作,则可以重写destroy()方法。
3、onBackProgress()与finish方法的区别?
(1)没有弹框,没有菜单,没有共享变换-----该情况,finish和onBackPressed是完全一样的。
(2)存在弹框、菜单等-----该情况,onBackPressed要先关闭popWindow
(3)存在共享变化-----该情况,finish不会调用变换动画,必须使用onBackPressed方法。
三、如何退出多个Activity
1、在Application中用List保存activity实例,然后逐一干掉
public class MyApplication extends Application {
private List<Activity> mList = new LinkedList<Activity>();
private static MyApplication mInstance;
private MyApplication() {
}
public static MyApplication getInstance() {
if (null == mInstance) {
synchronized (MyApplication.class) {
if (null == mInstance) {
mInstance = new MyApplication();
}
}
}
return mInstance;
}
//add Activity
public void addActivity(Activity activity) {
mList.add(activity);
}
public void closeActivity() {
if(mList!=null){
for (Activity activity : mList) {
if (activity != null)
activity.finish();
}
mList.clear();
}
}
}
2、使用注册广播的方式进行关闭Activity
3、使用OnActivityResult递归回调的方式关闭
4、使用setFlags的方式来关闭
(1)使用Intent的FLAG_ACTIVITY_CLEAR_TASK标记,这个标记可以清空要启动的activity所在的task栈。
什么意思呢?假如现在任务栈里面有A、B、C三个activity,这时C启动D,如果加上这个标记,那么启动D的同时就会移除A、B、C,这样这个任务栈里面就只剩新启动的D了。注意:这个标记需要与FLAG_ACTIVITY_NEW_TASK这个配合使用,否则不起作用。
(2)使用Intent的FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_NEW_TASK标记,这个标记可以清空要启动的activity上面的所有activity(与新启动的activity同处于一个task栈)。
什么意思呢?假如现在任务栈里面有A、B、 C、 D四个activity,这时D启动A,带上这两个标记,因为A已经在这个task栈中了,这个时候不会启动新的task栈,同时系统发现A的上面有B、C、D,所以系统会将这三个activity从task栈中移除,最终,这个task只剩下A了。
四、回退到指定的Activity
ep:比如我在个人中心页面跳转到A页面,输入完账号之后,到B页面,用户到了B页面,发现A页面的账号输入错误了,要返回,所以我在A跳B的时候就不能将A页面销毁,在B页面的,输入完毕密码之后,跳转到C页面去登录,当然登录完毕之后要回到个人中心页面,但是现在我们的输入账号的A页面还没有销毁,直接finish掉C页面的话会回到A页面.就达不到我们的初衷了.
方式1、
public static FirstActivity instance;
在A页面的onCreate中将当前Activity传入上面定义的静态中,
instance=this; //在onCreate里面写
我们哪里需要销毁A这个Activity就可以直接在这个Activity中,调用A的静态方法finish就可以了,
现在我们只要在C页面的登录点击事件中调用就可以了。
if(FirstActivity .instance!=null){//给一下判空
FirstActivity .instance.finish();//在其它的activity里面使用
}
方式2、
在实际的项目开发中也许会碰到一种情况,需要从A界面跳转到B界面,再从B界面跳转到C界面,再从C界面跳转到D界面,最后需要从D界面跳回到A界面,并且把B、C 、D界面都干掉。也许立马会有人觉得可以在B、C、D界面跳转时就finish()掉当前界面就可以了。但是如果需要在B、C、D界面之间可以正常的返回上一界面,那么在跳转的时候finish()掉当前界面就不合理了。
前面的A界面跳转到B界面,B界面跳转到C界面,C界面跳转到D界面都是正常的跳转,在最后D界面跳回A界面的时候这么写就可以了:
Intent intent = new Intent(D.this,A.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
这么写就可以从D界面跳回到A界面,并且B、C界面都已经被干掉了。
五、Activity之间传输数据
1、使用Intent的putExtra传递
2、使用Intent的Bundle传递
activity A
Intent intent = new Intent(MainActivity.this,TwoActivity.class);
//创建Bundle对象用来捆绑传递数据
Bundle bundle = new Bundle();
bundle.putString("String数据", str);
bundle.putInt("Int数据",5);
//把Bundle对象通过putExtra()方法放入intent对象中
intent.putExtra("bun", bundle);
//激活TwoActivity
startActivity(intent);
activity B
//获取Bundle对象
Intent intent = getIntent();
Bundle bundle = intent.getBundleExtra("bun");
//获取数据
String str = bundle.getString("String数据");
int a=bundle.getInt("Int数据")
//设置数据
tv.setText(str);
tv.setText(""+a);
3、使用onActivityResult
4、SharedPreferences传递数据
5、实现了Parcelable的对象及其数组
6、实现了 Serializable 的对象及其数组
import java.io.Serializable;
public class DataBean implements Serializable {
private String name;
private int age;
public DataBean() {
}
public DataBean(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
activity A
DataBean ss=new DataBean("carrie",18);
jump_in_item3.putExtra("数据",ss);
activity B
//反序列化数据对象
Serializable se = intent.getSerializableExtra("数据2");
if(se instanceof DataBean){
//获取到携带数据的DataBean对象db
DataBean db = (DataBean) se;
tv.setText(db.getName());
tv.setText(""+db.getAge());
}
7、使用静态变量传递数据