Android基础知识巩固系列 Android之四大组件——Activity(活动)

因为最近要面试,于是打算整理整理一下Android的基础知识,由于之前本人已经学习过大概的Android基础知识,这里主要讲这四大组件、五大存储、六大布局、网络请求等这些内容,其他一些等有时间再整理,话不多说。

应用组件(官方解释,需科学上网)

应用组件是 Android 应用的基本构建基块。每个组件都是一个不同的点,系统可以通过它进入您的应用。 并非所有组件都是用户的实际入口点,有些组件相互依赖,但每个组件都以独立实体形式存在,并发挥特定作用 — 每个组件都是唯一的构建基块,有助于定义应用的总体行为。

共有四种不同的应用组件类型。每种类型都服务于不同的目的,并且具有定义组件的创建和销毁方式的不同生命周期。

一、什么是Activity(活动)?

从官方的解释中可以看到:

Activity

Activity 表示具有用户界面的单一屏幕。例如,电子邮件应用可能具有一个显示新电子邮件列表的 Activity、一个用于撰写电子邮件的 Activity 以及一个用于阅读电子邮件的 Activity。 尽管这些 Activity 通过协作在电子邮件应用中形成了一种紧密结合的用户体验,但每一个 Activity 都独立于其他 Activity 而存在。 因此,其他应用可以启动其中任何一个 Activity(如果电子邮件应用允许)。 例如,相机应用可以启动电子邮件应用内用于撰写新电子邮件的 Activity,以便用户共享图片。

大概意思是说,Activity是一个可以让屏幕提供用户交互动作的组件,比如打电话、照相、发送邮件和查看地图等。简单来说,我们在应用程序中能看到的内容,绝大多数都是Activity组件提供的。 

 

二、Activity(活动)的生命周期

活动生命周期(官方解释)

系统中的活动作为活动堆栈进行管理。当一个新活动开始时,它被置于堆栈顶部并成为运行活动 - 前一个活动始终保持在堆栈中低于它,并且在新活动退出之前不会再次到达前台。

活动基本上有四种状态:

  • 如果活动位于屏幕的前景(位于堆栈顶部),则它处于活动状态或 正在运行
  • 如果活动失去焦点但仍然可见(即,新的非全尺寸或透明活动专注于您的活动),则会暂停活动。暂停的活动完全处于活动状态(它维护所有状态和成员信息并保持附加到窗口管理器),但可以在极低内存情况下被系统杀死。
  • 如果活动被另一个活动完全遮挡,则会停止活动。它仍然保留所有状态和成员信息,但是,它不再对用户可见,因此其窗口被隐藏,并且当其他地方需要内存时,它通常会被系统杀死。
  • 如果某个活动暂停或停止,系统可以通过要求完成活动或仅删除其进程来从内存中删除活动。当它再次显示给用户时,必须完全重新启动并恢复到之前的状态。

下图显示了Activity的重要状态路径。方形矩形表示当Activity在状态之间移动时可以实现的回调方法。彩色椭圆是活动所在的主要州

 Activity生命周期图:

Android基础知识巩固系列 Android之四大组件——Activity(活动)_第1张图片

您可能有兴趣在活动中监控三个关键循环:

  • 活动的整个生命周期发生在第一次通话到onCreate(Bundle)最后一次通话之间onDestroy()。活动将在onCreate()中完成所有“全局”状态设置,并释放onDestroy()中的所有剩余资源。例如,如果它有一个在后台运行的线程从网络下载数据,它可以在onCreate()中创建该线程,然后在onDestroy()中停止该线程。
  • 活动的可见生命周期发生在对onStart()相应调用 之间的调用之间 onStop()。在此期间,用户可以在屏幕上看到活动,尽管它可能不在前台并与用户交互。在这两种方法之间,您可以维护向用户显示活动所需的资源。例如,您可以BroadcastReceiver在onStart()中注册以监视影响UI的更改,并在用户不再看到您正在显示的内容时在onStop()中取消注册。onStart()和onStop()方法可以多次调用,因为活动对用户可见并隐藏。
  • 活动的前景生命周期发生在呼叫到 onResume()相应的呼叫之间 onPause()。在此期间,活动位于所有其他活动之前并与用户交互。活动可以经常在恢复和暂停状态之间进行 - 例如,当设备进入休眠状态,交付活动结果时,何时传递新意图 - 因此这些方法中的代码应该相当轻量级。

活动的整个生命周期由以下Activity方法定义。所有这些都是挂钩,您可以覆盖它们以在活动更改状态时执行适当的工作。所有活动都将实施onCreate(Bundle) 以进行初始设置; 许多人还将实现 onPause()提交数据更改,并准备停止与用户交互。在实现这些方法时,您应该始终调用您的超类。

 public class Activity extends ApplicationContext {
     protected void onCreate(Bundle savedInstanceState);

     protected void onStart();

     protected void onRestart();

     protected void onResume();

     protected void onPause();

     protected void onStop();

     protected void onDestroy();
 }
 

以上都是Google的官方解释的网站翻译。

以下是我从网站上看到写得比较好的一篇文章,于是我摘抄了下来,附上原网址,感谢分享

在说说Activity生命周期之前,我们先来理解"Activity返回栈”的概念。在Android中,多个Activity定义在一个Task中,也就是说一个Task是一组Activity的集合,然后Activity又被安排在back stack,即返回栈,是按照后进先出的规则进出栈的。如图:

  Android基础知识巩固系列 Android之四大组件——Activity(活动)_第2张图片

  当从手机中启动一个应用程序图标时,应用程序的Task随之也变成前台进程,如果首次启用时,发现不存在Task实例,那么系统会创建一个Task实例,然后把"main”Activity放入到stack中,默认是栈顶,这样一个Task就管理了一组栈,栈里管理多个Activity。当从Activity1中启动Activity2时,Activity1被推到栈底,Activity2变成栈顶,同理,Activity3进栈的过程和Activity2是一样的,如果我们按back按钮,则Activity3被弹出,系统会根据内存情况进行销售或者回收,Activity2则被推到栈顶,以此类推。当一直按back,返回到主页面,则所有的activitys被全部弹出,则task不复存在。

    同时,task有两种状态:Foreground和Background,前景和背景。当处于Background时,所有的activitys是停止的,当处于Foreground时,表示当前用户交互的应用程序。 

   Android基础知识巩固系列 Android之四大组件——Activity(活动)_第3张图片 

 比如两个应用程序A和B,我们刚开始启动了A应用程序,此时Task A是Foreground,用于与用户交互,当我们点击Home Button时,此时Task A变成Background,里面所有的activitys都是停止的,此时如果我们又启动了B应用程序,Task B又会被实例化,Task B变成Foreground,不过Task A仍然是Background,一直等待着被恢复。所以是Android也是一个多任务的系统,不同任务是可以被互相切换的。

    好了关于Task和Stack就先了解这么多,接下来讲讲Activity的生命周期。每个活动在其生命周期中最多可能会有四种状态

  • 运行状态
  • 暂停状态
  • 停止状态
  • 销毁状态

  3.1,运行状态

    当一个活动位于返回栈的栈顶时,这时活动就处于运行状态。系统最不愿意回收的就是处于运行状态的活动,因为这会带来非常差的用户体验。

    3.2,暂停状态

    当一个活动不再处于栈顶位置,但仍然可见时,这时活动就进入了暂停状态。比如对话框的形式只会占用屏幕中间的部分区域,你很快就会在后面看到这种活动,处于暂停状态的活动仍然是完全存活的,系统也不愿意去回收这种活动,只有在内存极低的情况下,系统才会去考虑回收这种活动。

    3.3,停止状态

    当一个活动不再处于栈顶位置,并且完全不可见的时候,就进入了停止状态。系统仍然会为这种活动保存相应的状态和成员变量,但是这并不是完全可靠的,当其他地方需要内存时,处于停止状态的活动有可能会被系统回收。

    3.4,销毁状态

    当一个活动从返回栈中移除后就变成了销毁状态。系统会倾向于回收处于这种状态的活动,从而保证手机的内存充足。

    3.5,七个方法

    Activity类中定义了七个回调方法,覆盖了活动生命周期的每一个环节。有如下七个方法:

  • onCreate()
  • onStart()
  • onResume()
  • onPause()
  • onStop()
  • onDestroy()
  • onRestart()

    onCreate():每个活动中我们都会重写这个方法,它会在活动第一次被创建的时候调用,比如完成一些初始化操作,加载布局、绑定事件等

    onStart():这个方法在活动不可见变为可见的时候调用

    onResume():这个方法在活动准备好和用户进行交互的时候调用,此时的活动一定位于返回栈的栈顶、并且处于运行状态。

    onPause():这个方法在系统准备去启动或者恢复另一个活动的时候调用。我们通常会在这个方法中将一些消耗CPU的资源释放掉,以及保存一些关键数据,但这个方法的执行速度一定要快,不然会影响到新的栈顶活动的使用。

    onStop():这个方法在活动完全不可见的时候调用。它和onPause()方法主要区别在于,如果启动的新活动是一个对话框式的活动,那么onPause()方法会得到执行,而onStop()方法不会执行。

    onDestroy():这个方法在活动被销毁之前调用,之后活动的状态将变为销毁状态。

    onRestart():这个方法在活动由停止状态变为运行状态之前调用,也就是活动被重新启动了。

 

    除此之外,活动又可以分为三种生存期

  • 完整生存期:活动在onCreate()和onDestroy()方法之间所经历的
  • 可见生存期:活动在onStart()和onStop()方法之间所经历的
  • 交互活动期:活动在onResume()和onPause()方法之间所经历的

    如图:

  

 

    3.6,活动被回收的情况

    前面说过了,当一个活动进入到停止状态,是有可能被系统回收的,如果我上次执行的临时数据和状态存在,则被回收的话,相当于临时数据被清空了,上次刚刚输入的文字全部都没了,那样的用户体验真是糟糕啊。所以Activity中还提供了一个onSaveInstanceState()回调方法,这个方法会保证一定在活动被回收之前调用,因此我们可以通过这个方法来解决会动被回收时临时数据得不到保存的情况。

  

     @Override
     protected void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
         String tempData = "Something you just typed";
         outState.putString("data_key", tempData);
     }

  执行以上代码,数据是保存下来了,那么应该在哪里恢复呢,你可以细心的观察到,在onCreate()方法里其实也有一个Bundle类型的参数,这个参数在一般情况下都是null,但是当活动被系统回收之前有通过onSaveInstanceState()方法来保存数据的话,这个参数就会带有之前所保存的全部数据,我们只需要再通过相应的取值方法来将数据取出即可。   

   if (savedInstanceState != null) {
        String tempData = savedInstanceState.getString("data_key");
        Log.d(TAG, tempData);
    }

 

三、Activity(活动)的启动模式

  每个活动(Activity)都有一个相应的启动模式,启动模式一共有四种,分别是standard、singleTop、singleTask、singleInstance,可以在AndroidManifest.xml中通过给标签指定android:launchMode属性来选择启动模式。

 

  4.1,standard

  standard是活动默认的启动模式,在不进行显示指定的情况下,所有活动都会自动使用这种启动模式。对于返回栈,在standard模式下,每当启动一个新的活动,它就会在返回栈中入栈,并处于栈顶的位置。对于standard模式的活动,系统不会在乎这个活动是否已经在返回栈中存在,每次启动都会创建该活动的一个新的实例。

    如图:

  Android基础知识巩固系列 Android之四大组件——Activity(活动)_第4张图片

       

    4.2,singleTop

    除了有standard模式之外,还存在一种叫做singleTop的模式,当活动的启动模式指定为singleTop,在启动活动时如果发现返回栈的栈顶已经是该活动,则认为可以直接使用它,不会再创建新的活动实例。

    如图:

    Android基础知识巩固系列 Android之四大组件——Activity(活动)_第5张图片

    

    4.3,singleTask

    使用singleTop模式很好地解决重复创建栈活动的问题,可是如果该活动并没有处于栈顶的位置,还是可能会创建多个活动实例的。如果想要让某个活动在整个应用程序的上下文中只存在一个实例呢?可以使用singleTask模式来启动。当活动的启动模式指定为singleTask,每次启动该活动时系统首先会在返回栈中检查是否存在该活动的实例,如果发现已经存在则直接使用该实例,并把在这个活动之上的所有活动统统出栈,如果没有发现就会创建一个新的活动实例。

    如图:

    Android基础知识巩固系列 Android之四大组件——Activity(活动)_第6张图片

  

    4.4,singleInstance

    singleInstance模式不同以上三个模式,指定为singleInstance模式的活动会启用一个新的返回栈来管理这个活动。通常应用以下场景,假设我们的程序中有一个活动是允许其他程序调用的,如果我们想实现其他程序和我们的程序可以共享这个活动的实例,那么该如何实现呢?使用前面三种启动模式肯定是做不到的,因为每个应用程序都会有自己的返回栈,同一个活动在不同的返回栈中入栈时必然是创建了新的实例。而使用了singleInstance模式就可以解决这个问题,在这种模式下会有一个单独的返回栈来管理这个活动,不管是哪个应用程序来访问这个活动,都共用的同一个返回栈,也就解决了共享活动实例的问题。

    如图:

    Android基础知识巩固系列 Android之四大组件——Activity(活动)_第7张图片

 

 

总结:

1.standard
标准模式,是系统的默认模式。每次启动一个Activity都会重新创建一个新的实例,不管这个实例是否已经存在。被创建的实例的生命周期符合典型情况下Activity的生命周期,onCreate()、onStart()、onResume()都会被调用。

2.singleTop
栈顶复用模式。在此模式下,如果想要跳转的Activity已经位于任务栈的栈顶,那么此Activity不会被重新创建。如果此Activity的实例已经存在但是不在栈顶,那么此Activity会被创建。同时onNewIntent()会被调用,而onCreate()、onStart()、onResume()不会被调用。

3.singleTask
栈内复用模式。是一种单实例模式。在此模式下,只要想要跳转的Activity在任务栈中存在,那么启动此Activity都不需要创建新的实例,和singleTop一样,会回调onNewIntent(),onCreate()、onStart()、onResume()不会被调用。

4.singleInstance
单实例模式,是一种加强的singleTask模式。除了具有singleTask所有的特性,还有在此模式下的Activity只能单独的在一个任务栈中。

 


 

使用场景(链接1,链接2):
1.standard该模式为默认模式,适用于大多数应用场景。

2.singleTop适合接收通知启动的内容显示页面。例如,某个新闻客户端的新闻内容页面,如果收到10个新闻推送,每次都打开一个新闻内容页面是很烦人的;或者说QQ消息推送,如果有100条消息,则要走100个跳转动画,并且消耗内存。

  • 但是要注意啊,从其他app跳转到singletop的app的时候是不会走onNewIntent的 上面提到了,所以遇到app相互调用的时候很少用singletop。

3.singleTask适合作为程序入口点。例如浏览器的主界面。不管从多少个应用启动浏览器,只会启动主界面一次,其余情况都会走onNewIntent,并且会清空主界面上面的其他页面。之前打开过的页面,打开之前的页面就ok,不再新建。适合程序开始的activity(频繁使用的主架构)可以用于主架构的activity,(什么新闻啊,侧滑啊)里面有好多fragment,他一般不会被销毁,他可以跳转其他的activity 再回主架构 其他的就销毁呗

4.singleInstance适合需要与程序分离开的页面。例如闹铃提醒,将闹铃提醒与闹铃设置分离。singleInstance不要用于中间页面,如果用于中间页面,跳转会有问题,比如:A -> B (singleInstance) -> C,完全退出后,在此启动,首先打开的是B。或者呼叫来电界面。

例如:闹钟里面 负责响的页面,打电话 接通的时候,地图显示的时候,他们都有一个特点 就是你做完这件事了都会返回到上一界面 而没有下一界面。 

你可能感兴趣的:(Android)