Hi,你们好,又见面啦,上一期咱们讲了如何安装AS,是否是已经有小伙伴火烧眉毛的建立了本身的项目并开始尝试了呢?那么这一期咱们主要为你们介绍Activity。做为Android的四大组件之一,Activity占据着很是重要的做用。本文将围绕Android的生命周期、启动模式、基本配置等方面进行介绍。java
应用程序的每个界面都是一个Activity,因此也有人称其为视图界面。从字面的意思去理解,Activity具备活动的意思,咱们在应用中进行的操做都是集中在Activity上面完成,例如拨号、拍照、发送email、看地图。每个activity被给设置到一个窗口,在上面能够绘制交互界面。 一个应用程序一般由多个activities组成,他们一般是松耦合关系,一般一个应用程序包含有一个主Activity,即点击桌面图标的时候首先进入的Activity。android
以一个简单的Activity的建立与使用示说明:面试
在Androd Studio 新建项目完成后,会自动建立一个 Java 文件,这个文件就是 Activity,由于它继承系统 framework 层提供的 Activity,这里 AppCompatActivity 是 Activity 的子类,咱们的 MainActivity 间接继承 Activity。数据结构
而且你会看到 MainActivity 强制重写了 onCreate 方法,在 onCreate 中,经过 setContentView 为 Activity 设置咱们自定义的页面布局文件。app
在 manifest 中注册Activityide
<activity android:name=".MainActivity" android:configChanges="orientation|screenSize" android:label="@string/app_name" android:launchMode="standard"> <intent-filter> <action android:name="myactoin2" /> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
Activity 必须在 AndroidManifest.xml 注册,若是没有注册这 Activity 就不能正常运行,其实在正常状况下在使用Android 中的四大组件(Activity,Service,BrocastReceiver,ContentProvider)时都须要再 AndroidManifest.xml 中注册。在上面的 xml 注册信息中,其中 <inten-filter>中指定布局
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
代表这个Activity是主Activity,在Android系统点击应用图标首先进入主Activity。动画
Activity是经过Intent用来在应用程序的Activity间启动、中止和传输。this
启动Activity的三种方法:spa
一、显示启动
在这里注册了第二个Activity ---- SecondActivity ,而且牢记前面的注册操做,咱们把 SecondActivity 注册到 Manifest 文件中。如今就能够在 MainActivity 中启动 SecondActivity。
Intent intent = new Intent(this, SecondActivity.class); //经过上下文Context和SecondActivity.java类的Class对象,建立 Intent 对象 startActivity(intent);//调用系统Framework 层提供的方法,启动 SecondActivity。
二、隐式启动
若 SecondActivity 在AndroidManifest.xml文件中配置 intent-filter 的 action 和 category、data,以下:
<intent-filter> <action android:name="myaction2"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="mycategory" /> </intent-filter>
那么能够经过以下方式启动 SecondActivity :
Intent intent = new Intent("myaction2"); startActivity(intent);
三、默认启动
经过桌面图标点击应用图标进入程序的第一个Activity,因其启动方式有别上述两个方式,将其划分为第三类的启动方式。 若Activity在AndroidManifest.xml文件的intent-filter的action和category,以下:
<intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter>
那么,点击桌面的应用图标便可启动Activity。
注:若是在N个Activity中都配置上述的action和category,那么桌面会有N个应用的图标,点击不一样的图标会进入对应的Activity。
Activity 的生命周期以下图:
(1) onCreate
表示Activity正在被建立,这是第一个执行的方法,在Activity的生命周期中只执行一次。在这个方法中作一些初始化工做,好比调用setContentView去加载界面布局,初始化Activity所须要的数据等。后续调用onStart()。
(2) onRestart
表示Activity正在从新启动,通常状况下,当前的Activity从不可见的状态变为可见状态时,onRestart就会被调用。这种情形通常是用户操做出现所致,好比用户按Home键回到桌面或者用户打开了一个新的Activity,这时候Activity就会暂停,接着用户又回到该Activity。后续调用onStart()。
(3) onStart
表示Activity正在被启动,即将开始。这个时候Activity是可见的,可是尚未出如今前台,不能和用户进行交互。这个时候能够理解为Activity已经显示出来,可是咱们还看不到。后续的方法是onResume()。
(4) onResume
表示Activity可见,而且已经出如今前台并开始活动,能和用户正常进行交互。须要注意的是onStart和onResume的区别,两者都是Activity可见,可是onStart时Activity还在后台,而onResume时Activity到了前台了,这时候能够开启动画或者获取独占性设备的操做如打开相机、获取麦克风等。
(5) onPause
表示Activity由前台转到后台,正常状况下,紧接着onStop就会被调用。这时仍然可见。若是这时候快速地回到当前Activity,那么onResume会被调用,这类状况属于极端状况,用户操做很难重现这一场景。此时能够作一些存储数据,中止动画等操做,可是注意不能太耗时,若是太耗时会影响到新的Activity的显示。onPause是先执行完,新的Activity的onCreate才会执行。onResume和onPause相对应。
(6) onStop
表示Activity即将中止,当前的Activity对用户不在可见。可稍微作些重量级的回收操做。后续的操做多是onRestart或者onDestroy或者一直保持这个状态。
(7) onDestory
表示Activity正在被销毁,是生命周期的最后一个回调,也是只调用一次。发生的条件是Activity自己已经执行完毕,或者系统资源不足须要回收资源将Activity销毁。
咱们考虑以下几类状况: 一、当一个Toast弹出的时候,会发生回调么? No 二、当一个AlertDialog弹出的时候,会发生回调么? No, 若是AlertDialog获取焦点,Activity会触发onWindowFocusChanged回调 三、当一个PopWindow弹出的时候,会发生回调么? No, 若是PopWindow获取焦点,如mPopupWindow.setFocusable(true),Activity会触发onWindowFocusChanged回调。 4.横竖屏切换时,会形成Activity被销毁而后从新建立。若在Activity配置android:configChanges="orientation",横竖屏切换时,只触发onConfigurationChanged( )回调,Activity不会被从新建立。
Activity 有四种启动模式,不一样的模式,对应这 Activity 对象的建立于复用策略,能够在 Manifest 和 代码中指定 Activity 的启动模式。
在探究什么是启动模式以前要弄请几个问题:
Android 任务栈又称为 Task,它是一个栈类型的数据结构:先进后出。它用于存储咱们的 Activity 组件。
每次打开一个新的 Activity 或 退出一个 Activity 都会在任务栈的结构中添加或减小一个 Activity,一个任务栈包含了一个 Activity 集合。Android 系统能够经过 Task 有序的管理每一个 Activity ,并决定那个 Activity 与用户进行交互:只用在栈顶的 Activity 才能够跟用户进行交互。
在应用程序退出时,必须把全部任务栈中的 Activity 清除栈时,任务栈才会被销毁。固然任务栈能够移动到后台,而且保存每一个 Activity 的状态。能够有序的给用户列出Activity的任务,同时也不会丢失 Activity 的信息。
应用程序中可能不止一个任务栈,某系状况状况下,单独的一个 Activity 能够独享一个任务栈,也会存在一个任务栈的 Activity 能够来自不一样的 App,同一个 App 中的 Activity 可能在不一样的任务栈当中。
在应用程序开发过程当中,通常都须要在多个 Activity 组件之间跳转,也可能须要在本应用中打开其余应用的可复用的 Activity。在开发过程当中须要跳转到原来已经开启的 Activity 实例,此时咱们但愿这个 Activity 能够被重用而不是再从新建立一个新的 Activity 实例,但根据 Android 系统的默认行为,每次都会为咱们建立一个新的 Activity 实例对象并添加到任务栈中,并且 Activity 的数据和信息状态都将会被保留 。
咱们能够在 MainActivity 中添加一个按钮,点击按钮跳转到 SecondActivity,而后在 SecondActivity 中添加两个按钮,点击一个按钮跳转到 MainActvity,在另外一个按钮的点击事件中添加以下代码:
//获取ActivityMananger ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); //获取任务栈 多是多个 List<ActivityManager.RunningTaskInfo> runningTasks = am.getRunningTasks(5); //获取当前的任务栈 ActivityManager.RunningTaskInfo runningTaskInfo = runningTasks.get(0); //获取当前任务栈中 Activity 个数,即当前没有换存活的 Activity 实例个数。 int numRunning = runningTaskInfo.numRunning; //Log 打印信息 Log.e("SecondActivity", "numRunning" + numRunning);
上面代码不用深究,主要目的是想说明系统默认状况下,当前任务栈中存活的 Activity 实例个数。当咱们在 MainActvity 中点击按钮跳转到 SecondActivity ,当跳转到 SecondActivity 在点击第一个按钮跳转到 MainActivity ,不断重复这个操做。最后当跳转的 SecondActivity 点击第一个按钮获取当前任务栈中的 Activity 个数。下面是方法和其对应运行时对应结果。
这样形成数据沉余,重复数据太多,最终可能还会致使内存溢出(OOM)。为解决这些问题,Android 系统提供了一套 Activity的启动模式来修改默认的 Activity 启动模式。
系统默认模式,每次启动一个Activity都会从新建立一个新的实例,而无论Activity是否已经建立了一个实例。
栈顶复用模式,系统启动时,系统会启动当前栈顶Activity是否是要启动的Activity,若是是则不须要建立新的Activity而直接引用这个Activity,若是不是那么建立新的Activity。系统会回调Activity的onNewIntent()的方法。
栈内复用模式,若是栈内已经存在了一个Activity的实例,那么Activity不会被从新建立,同时这个Activity的onNewIntent()方法会被回调,并将该Activity实例置于栈顶,原先处于该实例顶部的Activity实例会被出栈销毁。若是是其余程序启动Activity,那么它会从新建立一个任务栈。
单实例模式,是singleTask的增强版,具备singleTask全部特色,而且此种模式下Activity只有一个实例,而且只能单独的存在一个任务栈中。
启动模式通常分为两种:
Intent intent = new Intent(this, SecondActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//Flag startActivity(intent);
setFlags方法说明
//使用一个新的Task来启动Activity,但每一个Activity都将在一个新的Task中。 Intent.FLAG_ACTIVITY_NEW_TASK //使用singleTop模式来启动一个Activity。 Intent.FLAG_ACTIVITY_SINGLE_TOP //使用singleTask模式来启动一个Activity。 Intent.FLAG_ACTIVITY_CLEAR_TOP //使用singleTask模式来启动一个Activity,使用这种方式启动Activity,当Activity启动其余Activity的时候,该Activity会被销毁,不入栈。 Intent.FLAG_ACTIVITY_NO_HISTORY //方式没法指定 SingleInstance 模式,SingleInstances 只能在 AndroidManifest.xml 中声明。 Intent.setFlags
这里是一些在开发中常见的业务场景页面使用的页面启动模式:
做为Android的四大组件之一,而且也是项目开发过程当中最经常使用到的,小伙伴们要深入理解,并把它灵活的运用到项目中,固然这些也是面试中会问到的最基础问题。
PS:若是还有未看懂的小伙伴,欢迎加入咱们的QQ技术交流群:892271582,里面有各类大神回答小伙伴们遇到的问题哦~