Activity的启动与销毁,Activity之间跳转与传输数据

前言
当一个应用中有多个Activity时,就要涉及到Activity之间的跳转(即一个Activity启动跳转到另外一个Activity)、当返回上一个界面时,涉及到Activity的销毁(有可能只是销毁当前这一个Activity,也有可能销毁多个Activity,,还有可能跨
Activity销毁,等等)、还有一个问题就是Activity之间又是怎么传输数据的呢?好,待我好好回顾下喽~~
一、Activity的启动
指定程序中首次启动的Activity
当用户点击桌面的应用程序图标时,系统会调用app中被声明为launcher or main activity中的onCreate()方法,这个Activity被用来当做程序的主要切入点。这个Activity在功能清单文件中是这么声明的~

  <activity android:name=".FirstActivity">
            <intent-filter>
                <**action** android:name="android.intent.action.MAIN" />
                <**category** android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
 </activity>

当使用Android SDK工具来创建Android工程时,工程中就包含了一个默认的声明这个filte的activity类。
补充:什么是intentFilter?
IntentFilter:意图过滤器,主要用来过滤隐式意图,当用户进行一项操作的时候,Android系统会根据配置的 “意图过滤器” 来寻找可以响应该操作的组件,服务。
作用: IntentFilter通常是定义在AndroidManifest.xml文件中,也可以动态设置,通常是用来声明组件想要接受哪种Intent。例如,你如果为一个Activity设置了IntentFilter,你就可以在应用内或者其他应用中,用特定的隐式Intent来启动这个Activity,如果没有为Activity设置IntentFilter,那么你就只能通过显示Intent来启动这个Activity。

由FirstActivity启动SecondActivity,这时Intent意图就派上用场了~
来先了解下什么是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)有结果的页面跳转
①首先在FirstActivity中用方法startActivityForResult执行意图

@Override
  public void onClick(View v) {
      Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
      //startActivity(intent);
      startActivityForResult(intent,1);//给第一个页面标识为1
  }

②然后在SecondActivity的onCreate方法里准备回传的数据:
1)注册点击事件
2)初始化一个Intent对象,但不需要实现跳转,而需要用它的方法putExtra存储需要回传的数据
3)用方法setResult回传数据,参数表示(被请求访问界面即被动方的int型标志,Intent对象)
4) 用finish()结束目标页面的进程

@Override
   public void onClick(View v) {
       Intent intent=getIntent();
       intent.putExtra("second","I am second page");
       setResult(2,intent);
       finish();
   }

③最后再回到FirstActivity,用方法onActivityResult接收回传数据,参数表示(请求访问界面即主动方的int型标志,被请求访问界面即被动方的int型标志,Intent对象)

@Override
   protected void onActivityResult(int requestCode, int resultCode, Intent data) {
       super.onActivityResult(requestCode, resultCode, data);
       if (requestCode == 1 && resultCode == 2) {
           String fromSecondData = data.getStringExtra("second");
           Toast.makeText(this, fromSecondData, Toast.LENGTH_LONG).show();
           Log.i(TAG, "来自第二个页面回传的数据为:" + fromSecondData);
       }
   }

在这里插入图片描述
再来理解下标号1,标号2还有从第二个页面传回的Intent对象都在这个方法里实现了自己的价值。其实也可以这样理解,onActivityResult这个方法里的参数resultcode,是方便当前FirstActivity活动判断哪个页面返回的消息,在复杂情况下返回的页面太多时,每个页面的唯一标号能更好的帮助它们辨别彼此。
再来了解下显示Intent与隐式Intent的区别是什么?
显示Intent:明确指定目标组件的意图 Intent intent=new Intent(Context context,Class clazz); 当操作当前自己的应用组件时使用
隐式Intent:没有明确指定目标组件的意图,Intent(String action)当操作其他应用组件时使用
ep:打电话和发短信 都是用的隐式意图

 //隐士意图
			Intent intent=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 intent=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);

Intent的七大属性:参考[Intent七大属性(https://www.cnblogs.com/android-blogs/p/5690844.html)
二、Activity的关闭与销毁
调用finish()方法,用于关闭当前的Activity
系统源码解释:
在这里插入图片描述
当你打开的Activity已经执行完成并且需要被关闭的时候可以调用这个方法,当你按返回的时候,他将返回到当前Activity的发起者。

不使用finish():从activity 1中启动activity 2,然后在activity 2 启动activity 3,   这时按下返回键 程序就返回到了activity 2,再按下返回键 就返回到activity 1;
使用finish():从activity 1中启动activity 2,在activity 2调用finish(),然后在activity 2 启动activity 3,这时按下返回键 程序就直接返回了activity 1

销毁Activity,需重写onDestroy()方法
finish()方法与onDestroy()方法的区别?
finish()属于执行方法,而destroy()属于系统方法。finish()是在程序执行的过程中使用它来将对象销毁,而destroy()方法是在系统将该activity完全销毁(从内存中移除),释放资源空间。在写程序过程中,一般调用finish()。如果我们希望系统释放资源的时候,进行某些操作,则可以重写destroy()方法。
onBackPressed()方法也是用来返回到上一级页面的。
系统源码解释
在这里插入图片描述
当检测到用户按下后退*键时调用。默认实现只是完成当前活动,但你可以覆盖它来做你想做的任何事情。
onBackProgress()与finish方法的区别?
(1)没有弹框,没有菜单,没有共享变换-----该情况,finish和onBackPressed是完全一样的。
(2)存在弹框、菜单等-----该情况,onBackPressed要先关闭popWindow
(3)存在共享变化-----该情况,finish不会调用变换动画,必须使用onBackPressed方法。
三、如何退出多个Activity
①方式一:在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();
      }
    }
}

②使用注册广播的方式进行关闭Activity
③使用OnActivityResult递归回调的方式关闭
④使用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了。
使用一个ArrayList来管理Activity的引用,需要销毁时只需要遍历这个集合然后对每一个元素调用finish()即可。这样虽然可以实现,但是存在内存泄漏的风险,因为如果集合中引用Activity的元素不清空的话,Activity对象就没办法被垃圾回收器回收,造成内存泄露。
往需要销毁的activity发送广播,activity收到广播之后就自行销毁,这种实现方式效率不高,个人感觉也不优雅。
四、回退到指定的Activity
ep:比如我在个人中心页面跳转到A页面,输入完账号之后,到B页面,用户到了B页面,发现A页面的账号输入错误了,要返回,所以我在A跳B的时候就不能将A页面销毁,在B页面的,输入完毕密码之后,跳转到C页面去登录,当然登录完毕之后要回到个人中心页面,但是现在我们的输入账号的A页面还没有销毁,直接finish掉C页面的话会回到A页面.就达不到我们的初衷了.

public static FirstActivity instance;

在A页面的onCreate中将当前Activity传入上面定义的静态中.
instance=this;//在onCreate里面写
我们哪里需要销毁A这个Activity就可以直接在这个Activity中调用A的静态方法finish就可以了
现在我们只要在C页面的登录点击事件中调用就可以了

扫描二维码关注公众号,回复: 11406511 查看本文章
   if(FirstActivity .instance!=null){//给一下判空
       FirstActivity .instance.finish();//在其它的activity里面使用
   }

方式二、
在实际的项目开发中也许会碰到一种情况,需要从A界面跳转到B界面,再从B界面跳转到C界面,再从C界面跳转到D界面,最后需要从D界面跳回到A界面,并且把B、C 、D界面都干掉。也许立马会有人觉得可以在B、C、D界面跳转时就finish()掉当前界面就可以了。但是如果需要在B、C、D界面之间可以正常的返回上一界面,那么在跳转的时候finish()掉当前界面就不合理了。其实Android已经为我们提供了一种方法完成上述功能,只是一般很难找到而已,我也是一次机会在公司的一个老资格工程师那里知道,所以写出来和大家分享一下,非常的简单,只需要两行代码。
前面的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之间传输数据
通过Intent携带数据

  1. 8种基本数据类型及其数组
  2. String(String实现了 Serializable )/CharSequence实例类型的数据及其数组
  3. 实现了Parcelable的对象及其数组
  4. 实现了 Serializable 的对象及其数组
  5. 传递一个Bundle
    putExtra(String name, Xxx value): 保存额外数据
    intent.getXxxExtra(String name): 获取额外数据
    setData(Uri data): 设置有特定格式的uri数据
    至此,Activity的这几大问题就有着落了,自我感觉还是写的不够具体。如果后续在实践的过程中有实例了,我会在把具体的代码例子放上去的。

猜你喜欢

转载自blog.csdn.net/qq_37982823/article/details/86082187