《Android系统设计与开发》课件-第4章_第1页
《Android系统设计与开发》课件-第4章_第2页
《Android系统设计与开发》课件-第4章_第3页
《Android系统设计与开发》课件-第4章_第4页
《Android系统设计与开发》课件-第4章_第5页
已阅读5页,还剩85页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第4章Activity4.1Activity的概念4.2Activity的基本使用方法4.3Intent在Activity中的使用4.4Activity的生命周期4.5Activity的启动模式4.6Android系统的日志工具——Log本章总结

4.1Activity的概念

Activity是Android的四大组件之一,定义用户可以触摸看到的界面,主要用于和用户进行交互。Activity内使用各种界面组件,可实现交互动作;通过Activity,用户界面之间切换以及数据交换,进行数据传递。

4.2Activity的基本使用方法4.2.1手动创建Activity在手动创建一个Activity之前,我们需要先创建一个新的工程。打开AndroidStudio,点击FileNewNewProject,然后选择AddNoActivity(不添加Activity),并点击Next按钮,输入自定义项目名称和包名,也可以选择默认(此处输入的项目名是ActivityTest,包名为edu.tust.activitytest),如图4.1所示;接着点击Finish按钮,如图4.2所示,等待Gradle构建完成。至此一个没有添加Activity的新工程就创建完成了,下面开始在这个工程里手动创建一个Activity。

图4.1选择AddNoActivity

图4.2创建一个新的项目

将工程结构手动改为Project模式,如图4.3所示。

由于创建工程时选择的是AddNoActivity,因此app/src/main/java/edu.tust.activitytest目录下是空的,此时右击edu.tust.activitytest,选择NewActivityEmptyActivity,会弹出如图4.4所示的对话框,读者可自定义Activity名(这里默认为MainActivity)。对话框中的GenerateLayoutFile用于自动为MainActivity创建一个对应的布局文件;LauncherActivity用于自动将MainActivity设置为当前工程的主Activity。由于本小节学习的是手动创建一个Activity,因此不要勾选GenerateLayoutFile和LauncherActivity。图4.4手动创建Activity

4.2.2手动创建并加载布局

布局是用来显示界面内容的,下面介绍手动创建并加载布局。在app/src/main目录下,右键点击resNewDirectory,会弹出一个新建目录的窗口,如图4.5所示。新建一个名为layout的目录,点击OK按钮即可。

图4.5新建layout目录

接着选择新创建的layout目录,然后右键点击NewLayoutresourcefile,弹出一个新建布局资源文件的窗口,读者可自定义布局文件名(读者命名为main_layout),根元素默认选择为LinearLayout,如图4.6所示。最后点击OK按钮完成布局文件的创建。

图4.6新建布局文件

完成手动创建布局文件后,AndroidStudio上会出现布局编辑器,如图4.7所示。

图4.7布局编辑器

4.2.3在AndroidManifest文件中注册

AndroidManifest文件在app/src/main目录下,需要注意的是,所有的Activity都需要在AndroidManifest.xml中注册才能生效。

可以看到,Activity的注册声明要在<application>标签内,通过<activity>标签可对Activity进行注册。在<activity>标签中使用android:name可指明具体注册的Activity名,这里填入的.MainActivity是edu.tust.activitytest.MainActivity的缩写。因为在最外层<manifest>标签中已经通过package属性指定程序的包名,即edu.tust.activitytest,所以在注册Activity的时候这一部分可以省略,直接使用.MainActivity即可。

在AndroidManifest文件中还需要为主程序配置主Activity,即当程序运行时首先启动的Activity。为主程序配置Activity需要在<activity>标签的内部加入<intent-filter>标签,并且在<intent-filter>标签里面添加<actionandroid:name="ent.action.MAIN"/>和<categoryandroid:name="ent.category.LAUNCHER"/>声明,其中ent.action.MAIN决定程序启动时最先显示的Activity;ent.category.LAUNCHER表示Activity应该被列入系统启动器。

此外,还可以在<activity>标签内通过android:label为Activity指定标题栏内容,标题栏显示在Activity最顶部。

运行程序,结果如图4.8所示。

图4.8运行结果

4.2.4使用Toast提醒方式

Toast是Android系统提供的一种提醒方式,它可以在程序运行时提示用户一些简短的信息,这些信息并不会长时间显示,而是在一段时间后就消失了,不会占用屏幕的空间。

代码中通过findViewById()方法获取布局文件中定义的元素R.id.button,从而得到Button按钮实例。接着为Button按钮注册一个监听器,当点击按钮时便会执行监听器中的onClick()方法。Toast提醒的内容需要在onClick()方法中实现。通过Toast的静态方法makeText()创建一个Toast对象,然后通过调用show()方法在界面显示。其中makeText()方法中需要传入三个参数:第一个参数是Context,是Toast的上下文,由于Activity本身就是一个Context对象,因此使用当前Activity的名字即可;第二个参数是Toast需要显示的内容;第三个参数是内容显示的时长,可以选择Toast.LENGTH_SHORT或Toast.LENGTH_LONG这两个内置常量,其中Toast.LENGTH_SHORT显示的时长大约2秒,而Toast.LENGTH_LONG显示的时长约3.5秒。

运行程序,点击界面上的按钮,会看到Toast提醒信息,如图4.9所示。

图4.9Toast提醒

4.2.5使用Menu

由于手机屏幕的空间非常有限,在手机应用程序中如何充分利用屏幕空间显得非常重要。如果在Activity中需要显示多个菜单,那么可以使用Android提供的一种方式——Menu,它不仅不占用屏幕空间,还可以让许多菜单里的界面都显示出来。

右键点击res目录下的NewDirectory,新建一个menu文件夹,如图4.10所示,点击OK按钮完成创建。

图4.10新建menu文件夹

在新建的menu文件夹下右键点击NewMenuresourcefile,新建一个名为main的资源文件,如图4.11所示,点击OK按钮完成创建。图4.11新建Menu资源文件

回到MainActivity.java中,在AndroidStudio的菜单栏中选择CodeOverrideMethods…(也可以通过快捷方式Ctrl+O),这时会弹出如图4.12所示的窗口,找到onCreateOptionsMenu()并选中,点击OK按钮。

图4.12重写onCreateOptionsMenu()方法

在onCreateOptionsMenu()方法中通过getMenuInflater()方法可以得到MenuInflater对象,然后调用inflate()方法就可以给当前Activity(MainActivity)创建菜单。在inflate()方法中接收两个参数,第一个参数是指定资源文件;第二个参数是指定菜单项将添加到哪一个Menu对象中。方法返回true,表示允许所创建的菜单显示出来;返回false,表示不允许所创建的菜单显示出来。

完成重写onCreateOptionsMenu()方法后还需要定义菜单响应事件,这样创建的菜单不仅可以显示出来,还可以有响应事件。定义菜单响应事件需要重写onOptionsItemSelected()方法同上(或使用快捷方式:Ctrl+O),选中onOptionsItemSelected(),点击OK按钮,如图4.13所示。

图4.13重写onOptionsItemSelected()方法

重新运行程序,发现屏幕的右上方多了一个“”的符号,点击后看到新创建的菜单项,然后点击其中任一菜单项都会有相应的Toast提醒。具体如图4.14所示。

图4.14点击带菜单按钮的Activity运行界面

4.2.6销毁Activity

前面学习了如何创建Activity,接下来学习如何销毁Activity。其实销毁Activity非常简单,点击返回键就可以销毁当前Activity。下面我们添加一个按钮,通过点击按钮的方式销毁Activity。

4.3Intent在Activity中的使用

Intent大致可以分为显式Intent和隐式Intent两种。Intent具有多个构造函数的重载,其中一个是Intent(ContextpackageContext,Class<?>cls),该构造函数接收两个参数,第一个参数Context要求提供一个启动Activity的上下文;第二个参数Class指定需要启动的目标Activity。

4.3.1使用显式Intent

在4.2节创建的工程中,选中app/src/main/java/edu.tust.activitytest目录,右键点击NewActivityEmptyActivity,在弹出的对话框中自定义将创建的Activity名(SecondaryActivity)和布局名(secondary_layout),选中GenerateLayoutFile,但不要勾选LauncherActivity,如图4.15所示。

图4.15创建SecondaryActivity

点击Finish按钮完成创建,AndroidStudio会自动生成SecondaryActivity.java和Secondary_layout.xml两个文件。

可以看到,程序中使用的是LinearLayout布局,然后在AndroidManifest.xml中为AndroidStudio自动生成的SecondaryActivity加一个label标签,

重新运行程序,在主Activity界面上点击“启动第二个活动”,跳转到我们创建的第二个Activity,如图4.16所示。

图4.16显示Intent从第一个Activity跳转至第二个Activity

4.3.2使用隐式Intent

隐式Intent中并不明确指出想要启动哪一个Activity,而是指定了一系列更为抽象的action和category等信息,然后由系统去分析Intent,并启动目标Activity。使用隐式Intent需要经过以下步骤:

首先,在AndroidManifest.xml文件中的<activity>标签下,为创建的SecondaryActivity添加<intent-filter>,并指定SecondaryActivity能够响应的action和category。

可以看到,在<activity>标签中指明了当前Activity可以响应edu.tust.activitytest.ACTION_START这个action,在<category>标签中包含一些附加信息,这里的ent.category.DEFAULT是一种默认的category,在调用startActivity()方法时会自动将category添加到Intent中。需要注意的是,只有<action>和<category>中的内容同时匹配上Intent中指定的action和category时,对应的Activity才会响应。

修改main_layout.xml中的代码,在主Activity的布局文件中再添加一个Button按钮。

重新运行程序,点击“启动第二个活动(隐式)”按钮,程序跳转到第二个Activity,如图4.17所示。

图4.17隐式Intent启动Activity

最后重新运行程序,点击“启动第二个活动(带CATEGORY)”按钮,同样会跳转到SecondaryActivity,如图4.18所示。

图4.18带CATEGORY从第一个Activity跳转至第二个Activity

4.3.3使用隐式Intent启动其他Activity

使用隐式Intent不仅可以启动程序内部的Activity,还可以启动程序外部的Activity。比如需要在应用程序中展示网页时,不用专门实现一个浏览器,只需调用系统浏览器打开网页即可。使用隐式Intent使得在多个Android应用之间实现功能共享成为可能。

重新运行程序,然后点击“打开TUST官网”按钮,这时会自动打开浏览器并跳转到TUST官网,如图4.19所示。

图4.19隐式Intent启动系统浏览器

此外还可以在<intent-filter>标签中配置一个<data>标签,用于更精确地指定当前Activity所能响应的数据。<data>标签属性如表4.1所示。

4.3.4传递数据给下一个Activity

Intent中提供了一系列putExtra()方法的重载,将要传递的数据暂时存在Intent中,在启动另一个Activity后,只需要把数据从Intent中取出即可。

传递的是字符串,所以使用getStringExtra()方法来获取传递的数据。如果传递的是整型数据,则使用getIntExtra()方法;如果传递的是布尔型数据,则使用getBooleanExtra()方法,以此类推。

重新运行程序,点击刚添加的按钮,会跳转到SecondaryActivity,观察Logcat中打印的信息,如图4.20所示,表明已经成功将数据从MainActivity传递给SecondaryActivity。

图4.20Logcat打印的信息

4.3.5返回数据给上一个Activity

返回数据给上一个Activity需要用到startActivityForResult()方法,该方法接收两个参数,第一个参数是Intent;第二个参数是请求码,用于在回调中判断数据的来源。

可以看到,将要传给MainActivity的数据存放在intent中,然后调用setResult()方法。setResult()方法接收两个参数,第一个参数用于向上一个Activity返回结果,一般有RESULT_OK和RESULT_CANCEL两个值,第二个参数把带有数据的intent传回去,接着调用finish()方法销毁该Activity。

重新运行程序,点击MainActivity界面按钮便会跳转至SecondaryActivity,然后点击SecondaryActivity界面上的按钮便可以返回到MainActivity,这时注意观察Logcat的打印信息,如图4.21所示。图4.21Logcat打印的信息

4.4Activity的生命周期

Android中使用任务(Task)来管理Activity,一个任务就是一组存放在栈里的Activity集合,这里引入返回栈(BackStack)的概念。栈是一种后进先出的数据结构,默认情况下,每当启动一个新的Activity时,它都会在返回栈中入栈,并且处于栈顶的位置。每当按下Back返回键或者调用finish()方法销毁一个Activity时,处于栈顶的Activity就会出栈,此时上一个入栈的Activity就会重新处于栈顶的位置。系统总是显示处于栈顶位置的Activity。返回栈的示意图如图4.22所示。

图4.22返回栈的示意图

4.4.1Activity的四种状态

每个Activity在其生命周期中都有四种状态,分别为运行状态、暂停状态、停止状态和销毁状态。

1.运行状态

当一个Activity位于返回栈的栈顶时,它处于可见并可与用户交互的激活状态,即为运行状态。

2.暂停状态

当一个Activity不再处于返回栈的栈顶位置,但依然可见时,该Activity就会进入暂停状态。并不是所有的Activity都会占满整个屏幕,例如,对话框形式的Activity只会占用部分屏幕空间。这种处于暂停状态的Activity依然是存活的。

3.停止状态

当一个Activity不再处于返回栈的栈顶位置,并且完全不可见时,该Activity就处于停止状态。此时系统仍然会给处于停止状态的Activity保存相应的状态和成员变量。但是,当其他地方需要内存时,处于停止状态的Activity就有可能被系统回收。

4.销毁状态

当一个Activity从返回栈中被移除后,该Activity就变成了销毁状态。

4.4.2Activity的生存期

在不同的状态下,Android系统对Activity类中的方法进行相应的回调。因此,在程序中编写Activity时,一般都是继承Activity类并重写相应的回调方法。Activity类中定义了7个回调方法,覆盖了Activity生命周期的每一个环节。

(1) onCreate()。

每当新创建一个Activity时,都会看到该方法,因为每个Activity中都需要重写onCreate()方法,完成Activity的初始化操作,例如加载布局、绑定事件等。

(2) onStart()。

当某一个Activity由不可见变为可见的时候,调用onStart()方法。

(3) onResume()。

当Activity准备好与用户进行交互,并且该Activity一定位于返回栈的栈顶位置时,处于运行状态,则调用onResume()方法。

(4) onPause()。

当系统准备去启动或者恢复另一个Activity时,调用onPause()方法。这个方法的执行速度一定要快,否则会影响到新的栈顶Activity的使用。

(5) onStop()。

当Activity处于完全不可见的时候调用onStop()方法。该方法与onPause()方法的区别是,如果启动的新Activity是对话框Activity,覆盖了原有Activity,但原有Activity仍然可见,则执行的是onPause()。

(6) onDestroy()。

在Activity被销毁之前调用onDestroy()方法,之后Activity的状态将会变成销毁状态。

(7) onRestart()。

在Activity由停止状态变为运行状态之前调用onRestart()方法,Activity将被重新启动。

以上七个方法中除了onRestart()方法,其他方法都是两两相对的,所以又可以将Activity分为3个生存期。

(1)完整生存期。

Activity从onCreate()方法到onDestroy()方法之间所经历的就是完整生存期。

(2)可见生存期。

Activity从onStart()方法到onStop()方法之间所经历的就是可见生存期。在可见生存期内,无论该Activity与用户是否有交互,Activity对用户都是可见的。

(3)前台生存期。

Activity从onResume()方法到onPause()方法之间所经历的就是前台生存期。在前台生存期内,Activity总是处于运行状态,并且此时的Activity可以与用户进行交互。

Activity生命周期示意图如图4.23所示。

图4.23Activity的生命周期示意图

以看到,在onCreate()方法中分别为添加的两个Button按钮注册了点击事件,点击第一个Button,会跳转至正常Activity;点击第二个Button,会跳转至对话框Activity。然后在Activity的7个回调方法中分别打印一句话,这样能够通过Logcat更加直观地理解Activity的生命周期。

一切就绪后,运行程序,其界面如图4.24所示。

图4.24FirstActivity主界面

此时注意观察Logcat中打印的信息,如图4.25所示。图4.25启动程序时的Logcat

从Logcat中可以看到,在FirstActivity第一次被创建时,会依次执行onCreate()方法、onStart()方法和onResume()方法。然后点击第一个按钮,则会跳转至SecondActivity,并注意观察Logcat中的信息,如图4.26和图4.27所示。

图4.26SecondActivity界面

图4.27打开SecondActivity时的Logcat

我们可以看到Logcat上出现onPause和onStop,这是因为SecondActivity已经把FirstActivity完全遮挡住,所以会执行onPause()方法和onStop()方法。接着,按下Back返回键,回到FirstActivity,此时注意观察Logcat,如图4.28所示。图4.28按下Back键返回至FirstActivity时的Logcat

onRestart()方法最先被执行,这是因为之前的FirstActivity已经处于停止状态,那么重新回到运行状态需要执行onRestart()方法、onStart()方法以及onResume()方法,但是相比首次运行时,这次并没有执行onCreate()方法,因为FirstActivity并没有重新创建。然后再点击第二个按钮,启动ThirdActivity,并注意观察Logcat,如图4.29和图4.30所示。图4.29ThirdActivity界面图4.30打开ThirdActivity时的Logcat

由于ThirdActivity是一个对话框式的Activity,启动后并没有完全遮挡住FirstActivity,此时的FirstActivity只是进入了暂停状态,所以只执行了onPause()方法。按下Back返回键后会回到FirstActivity,相应地也只会执行onResume()方法,如图4.31所示。图4.31从ThirdActivity回到FirstActivity时的Logcat

再按一次Back返回键,则会退出该程序,这时观察Logcat,如图4.32所示。图4.32退出程序时的Logcat

4.4.3系统回收Activity

当一个Activity进入停止状态时,是有可能被系统回收的。设想一下,如果在FirstActivity中输入一段文字,然后启动SecondActivity,这时倘若由于系统内存不足而导致FirstActivity被回收,那么当程序从SecondActivity返回到FirstActivity时,会发现刚刚输入的文字全部消失了。这就使得Activity进入停止状态且被系统回收后,之前Activity上的数据和状态全部都被销毁。

那么该如何解决Activity被回收时需要临时保存数据的问题呢?Activity中提供了onSaveInstanceState()回调方法,该方法可以有效解决上述问题。onSaveInstanceState()方法会携带一个Bundle类型的参数,Bundle提供了一系列的方法用于保存数据,如可以使用putString()保存字符串、使用putInt()保存整型数据等。每个方法需要传入两个参数,第一个参数是键,第二个参数是需要保存的内容。

4.5Activity的启动模式

在实际项目中,应根据特定的需求为每一个Activity指定恰当的启动模式。Activity的启动模式共有四种,分别为:standard、singleTop、singleTask和singleInstance。在使用时可以通过在AndroidManifest.xml中给<activity>标签指定android:launchMode属性来选择启动模式。

1. standard

standard是Activity默认的启动模式,前面创建的Activity都没有指明启动模式,但都能够正常使用,这是因为当不指定Activity的启动模式时,Activity就会以默认的standard模式启动。standard模式的原理示意图如图4.33所示,在该模式下,每当启动一个新的Activity时,它就会在返回栈中入栈,并且处于栈顶位置。系统不会去判断该Activity是否已经存在返回栈中,而是每次启动都会创建该Activity的一个新的实例。

图4.33standard模式的原理示意图

运行程序,然后在FirstActivity界面点击两次按钮,这时观察Logcat中的信息,如图4.34所示。图4.34standard模式下的Logcat信息

2. singleTop

在singleTop模式下,当启动Activity时,如果发现该Activity在返回栈的栈顶,则会直接使用它,而不会像standard模式一样再次创建新的Activity实例。singleTop模式的原理示意图如图4.35所示。

图4.35singleTop模式的原理示意图

重新运行程序,可以看到Logcat中已经创建了一个FirstAct

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论