[关闭]
@stepbystep 2015-01-24T06:26:37.000000Z 字数 13002 阅读 3292

Activity详解

Android

本课程知识点

课前复习

Android studio工程目录结构图

img

布局的常见属性

 android:layout_width="match_parent":当前控件的布局宽度(layout_width)为匹配父容器(match_parent)
 android:layout_height="match_parent":当前控件的布局高度(layout_height)为匹配父容器(match_parent)
 android:layout_width="wrap_content":当前控件的布局宽度为包裹内容(内容有多宽,这个控件就多宽)
 android:layout_height="wrap_content":当前控件的布局高度为包裹内容(内容有多高,这个控件就多高)

布局文件中 '@' 符号对于资源的导航引用

  1. <!-- @string/hello_world:代表引用R.java文件中的string静态内部类中的hello_world静态成员;
  2. 对应的资源在res/values/strings.xml中的
  3. <string name="hello_world">Hello world!</string>
  4. name="hello_world"这个键对应的内容:Hello world!
  5. -->
  6. <TextView android:text="@string/hello_world" android:layout_width="wrap_content" android:layout_height="wrap_content" />

Activity文件中, 资源的导航

  1. /*
  2. * 将Activity到用户界面设定为R.layout.activity_main,即
  3. * res/layout/activity_main.xml
  4. * 可在build/generated/source/r/debug/com../R.java下查看layout静态内部类中的activity_main的静态成员
  5. * 对应的是res/layout/activity_main.xml*/
  6. setContentView(R.layout.activity_main);

AndroidManifest.xml 文件配置启动activity

  1. <activity
  2. android:name=".MainActivity"
  3. android:label="@string/app_name" >
  4. <intent-filter>
  5. <action android:name="android.intent.action.MAIN" />
  6. <category android:name="android.intent.category.LAUNCHER" />
  7. </intent-filter>
  8. </activity>

Activity简介

简单的说:Activity就是布满整个窗口或者悬浮于其他窗口上的交互界面。在一个应用程序中通常由多个Activity构成,这每个Activity都需要在AndroidManifest.xml中进行配置,否则会出现无法启动Activity的错误,其中,默认启动的主Activity需要在其<activity> </activity>标签中加上如下设置

  1. <intent-filter>
  2. <action android:name="android.intent.action.MAIN" />
  3. </intent-filter>

当程序第一次运行时用户就会看这个Activity,这个Activity可以通过启动其他的Activity进行相关操作。 注:每个Activity都可以启动一个或多个Activity,而每一个启动的Activity都可以向它的Activity返回信息。


Activity的建立和使用


  1. 为了使用一个Activity,需要首先实现一个继承了Activity的子类,并重写父类中的一些方法。
  2. 一般都会重写onCreate方法,在Activity启动的时候调用,我们一般将一些初始化的工作放在这个方法里面执行。
  3. 在onCreate()方法中, 必须执行super.onCreate(savedInstanceState),否则这个Activity启动的时候会抛出异常。
  4. 实现一些交互相关的代码
  5. 在AndroidManifest.xml文件中注册Activity,并配置一些Activity的属性。如:设置Activity横竖屏状态,标签,name属性,是否未主Activity等。

    android:theme activity的样式主题, 如果没有设置,则activity的主题样式从属于应用程序, 参见元素的theme属性
    android:name activity的类名, 必须指定
    android.icon , android:label


Activity的生命周期

Activity的四种基本状态

Activity的生命周期详解

图解如下:
img

生命周期实验

说明,为了熟悉整个流程,本次实验采用全部手写,不用系统生成功能
本实验需要三个Activity,MainActivity,DialogActivity,CoverActvity

新建工程

新建工程ActivityLifeCycle, 在Add an Activity to Mobile页面时选择No Activity,进入主界面。
选择Project视图
img

新建布局文件

img

输入layout_main_activity.xml 选择根节点为LinearLayout

img
打开layout_maain_activity.xml (app/src/main/res/layout/layout_main_activity.xml)

新建后结果如下
img

修改内容如下:
app/src/main/res/layout/activity_main.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!-- 什么是线性布局?
  3. 线性布局分两种,一种是垂直式,每一行只有一个元素,另一种是水平式,每一列只有一个元素
  4. 用android:orientation属性来表示,LinearLayout默认是水平布局。
  5. 因此,此时要注意,android:orientation="vertical" 必须要加上-->
  6. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  7. android:layout_width="match_parent"
  8. android:layout_height="match_parent"
  9. android:orientation="vertical">
  10. <!-- Button是一个按钮的控件, text属性表示按钮上显示的文字-->
  11. <Button
  12. android:id="@+id/btn_cover"
  13. android:layout_width="match_parent"
  14. android:layout_height="wrap_content"
  15. android:layout_margin="10dp"
  16. android:text="completely cover open"
  17. />
  18. <Button
  19. android:id="@+id/btn_dialog"
  20. android:layout_width="match_parent"
  21. android:layout_height="wrap_content"
  22. android:layout_margin="10dp"
  23. android:text="dialog mode open"
  24. />
  25. </LinearLayout>

app/src/main/res/layout/activity_cover.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent" android:layout_height="match_parent">
  4. <TextView
  5. android:layout_width="wrap_content"
  6. android:layout_height="wrap_content"
  7. android:text="I am CoverActiviy!"/>
  8. </LinearLayout>
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent" android:layout_height="match_parent">
  4. <TextView
  5. android:layout_width="wrap_content"
  6. android:layout_height="wrap_content"
  7. android:padding="30dp"
  8. android:text="I am DialogActiviy!"/>
  9. </LinearLayout>
  1. package com.example.shiyanlou.activitylifecycle;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. /**
  5. * Created by shiyanlou on 15-1-16.
  6. */
  7. public class CoverActivity extends Activity {
  8. @Override
  9. protected void onCreate(Bundle savedInstanceState) {
  10. super.onCreate(savedInstanceState);
  11. setContentView(R.layout.activity_cover);
  12. }
  13. }
  1. package com.example.shiyanlou.activitylifecycle;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. /**
  5. * Created by shiyanlou on 15-1-16.
  6. */
  7. public class DialogActitivy extends Activity{
  8. @Override
  9. protected void onCreate(Bundle savedInstanceState) {
  10. super.onCreate(savedInstanceState);
  11. setContentView(R.layout.activity_dialog);
  12. }
  13. }
  1. package com.example.shiyanlou.activitylifecycle;
  2. import android.app.Activity;
  3. import android.content.Intent;
  4. import android.os.Bundle;
  5. import android.view.View;
  6. /**
  7. * Created by shiyanlou on 15-1-16.
  8. */
  9. public class MainActivity extends Activity{
  10. @Override
  11. protected void onCreate(Bundle savedInstanceState) {
  12. super.onCreate(savedInstanceState);
  13. setContentView(R.layout.activiy_main);
  14. System.out.println("MainActivity-> onCreate()");
  15. findViewById(R.id.btn_cover).setOnClickListener(new View.OnClickListener() {
  16. @Override
  17. public void onClick(View v) {
  18. Intent intent = new Intent(MainActivity.this, CoverActivity.class);
  19. startActivity(intent);
  20. }
  21. });
  22. findViewById(R.id.btn_dialog).setOnClickListener(new View.OnClickListener() {
  23. @Override
  24. public void onClick(View v) {
  25. Intent intent = new Intent(MainActivity.this, DialogActitivy.class);
  26. startActivity(intent);
  27. }
  28. });
  29. }
  30. @Override
  31. protected void onStart() {
  32. super.onStart();
  33. System.out.println("MainActivity-> onStart()");
  34. }
  35. @Override
  36. protected void onStop() {
  37. super.onStop();
  38. System.out.println("MainActivity-> onStop()");
  39. }
  40. @Override
  41. protected void onPause() {
  42. super.onPause();
  43. System.out.println("MainActivity-> onPause()");
  44. }
  45. @Override
  46. protected void onRestart() {
  47. super.onRestart();
  48. System.out.println("MainActivity-> onRestart()");
  49. }
  50. @Override
  51. protected void onResume() {
  52. super.onResume();
  53. System.out.println("MainActivity-> onResume()");
  54. }
  55. @Override
  56. protected void onDestroy() {
  57. super.onDestroy();
  58. System.out.println("MainActivity-> onDestroy()");
  59. }
  60. }
  1. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  2. package="com.example.shiyanlou.activitylifecycle">
  3. <application android:allowBackup="true" android:label="@string/app_name"
  4. android:icon="@drawable/ic_launcher" android:theme="@style/AppTheme">
  5. <!-- 注册activity-->
  6. <activity android:name=".MainActivity"
  7. android:label="ActivityLifeCycle">
  8. <intent-filter>
  9. <action android:name="android.intent.action.MAIN"></action>
  10. <category android:name="android.intent.category.LAUNCHER"></category>
  11. </intent-filter>
  12. </activity>
  13. <!-- 注册activity-->
  14. <activity android:name=".CoverActivity"
  15. android:label="CoverActivity">
  16. </activity>
  17. <!-- 注册activity
  18. 设置theme为Dialog样式-->
  19. <activity android:name=".DialogActitivy"
  20. android:label="DialogActitivy "
  21. android:theme="@style/Theme.AppCompat.Dialog">
  22. </activity>
  23. </application>
  24. </manifest>

最后的工程结构如下图:
img

实验准备

为了方便在logcat查看输出内容,我们先编辑滤器,前面已经讲过。
img

此后我们可以看到logcat中已经过滤了信息,同时我们将界面返回到home界面(一直按返回键),并清空信息
img

将logcat拉大,方便查看
img

测试程序

运行结果截图: 此处的AcitivityLifeCycle对应Manifest.xml文件中的lable

  1. <!-- 注册activity-->
  2. <activity android:name=".MainActivity"
  3. android:label="ActivityLifeCycle">

img

Activity完整生命周期演示

点击进入与MainActivity界面,如下:
img
查看logcat
在Activity启动时函数的调用过程:onCreate--->onStart()--->onResume();
img

按手机上的返回键(主动销毁当前的Activity)后函数的调用过程:onPause()-->onStop()-->onDestroy();
img

(如果点击不灵,可以按键盘的Esc键,效果一样)
此处列举一下模拟器和键盘的按键对应关系

键盘按键 模拟器对应键
Home Home key Home键
ESC Back Key 后退键
F2 Menu key 菜单键
F3 Call key 发送拨号键
F4 End Call key 结束通话或者说 红键
上下左右 方向键
Enter 确定键

Activity的完整声明周期的函数调用过程:
onCreate()-->onStart()-->onResume()--->onPause()-->onStop()--->onDestroy();

onRestart()方法的调用过程演示:

启动Activity: onCreate()-->onStart()--->onResume();
按手机上的Home键(返回手机的桌面)调用的方法:onPause()-->onStop();
img

单击手机上这个程序的桌面图标(重新启动Activity)的函数调用过程:onRestart()-->onStart()-->onResume();
img

Activity可视生命周期函数的调用过程:onPause()--->onStop()--->onRestart()--->onStart()--->onResume();

Activity前台生命周期演示:

Activity启动调用的方法:onCreate()-->onStart()-->onResume();

点击第二个按钮以对话框方式打开新的Activity
效果如下:此处的间隔就是因为padding=30dp语句的作用
img

logcat 截图:
img
此时按手机上的返回键(销毁当前的对话框):
img

Activity的前台生命周期的调用过程:onPause()---->onResume();

Activity互相启动时函数的调用

为了测试方便需要修改代码如下:
修改CoverActivity.java如下

  1. package com.example.shiyanlou.activitylifecycle;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. /**
  5. * Created by shiyanlou on 15-1-16.
  6. */
  7. public class CoverActivity extends Activity {
  8. @Override
  9. protected void onCreate(Bundle savedInstanceState) {
  10. super.onCreate(savedInstanceState);
  11. setContentView(R.layout.activity_cover);
  12. System.out.println("CoverActivity -> onCreate()");
  13. }
  14. @Override
  15. protected void onStart() {
  16. super.onStart();
  17. System.out.println("CoverActivity -> onStart()");
  18. }
  19. @Override
  20. protected void onStop() {
  21. super.onStop();
  22. System.out.println("CoverActivity -> onStop()");
  23. }
  24. @Override
  25. protected void onPause() {
  26. super.onPause();
  27. System.out.println("CoverActivity -> onPause()");
  28. }
  29. @Override
  30. protected void onRestart() {
  31. super.onRestart();
  32. System.out.println("CoverActivity -> onRestart()");
  33. }
  34. @Override
  35. protected void onResume() {
  36. super.onResume();
  37. System.out.println("CoverActivity -> onResume()");
  38. }
  39. @Override
  40. protected void onDestroy() {
  41. super.onDestroy();
  42. System.out.println("CoverActivity -> onDestroy()");
  43. }
  44. }
  1. package com.example.shiyanlou.activitylifecycle;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. /**
  5. * Created by shiyanlou on 15-1-16.
  6. */
  7. public class DialogActitivy extends Activity{
  8. @Override
  9. protected void onCreate(Bundle savedInstanceState) {
  10. super.onCreate(savedInstanceState);
  11. setContentView(R.layout.activity_dialog);
  12. System.out.println("DialogActitivy -> onCreate()");
  13. }
  14. @Override
  15. protected void onStart() {
  16. super.onStart();
  17. System.out.println("DialogActitivy -> onStart()");
  18. }
  19. @Override
  20. protected void onStop() {
  21. super.onStop();
  22. System.out.println("DialogActitivy -> onStop()");
  23. }
  24. @Override
  25. protected void onPause() {
  26. super.onPause();
  27. System.out.println("DialogActitivy -> onPause()");
  28. }
  29. @Override
  30. protected void onRestart() {
  31. super.onRestart();
  32. System.out.println("DialogActitivy -> onRestart()");
  33. }
  34. @Override
  35. protected void onResume() {
  36. super.onResume();
  37. System.out.println("DialogActitivy -> onResume()");
  38. }
  39. @Override
  40. protected void onDestroy() {
  41. super.onDestroy();
  42. System.out.println("DialogActitivy -> onDestroy()");
  43. }
  44. }

重新运行程序

以完全覆盖的形式打开ActivityB

点击第一个按钮 completely cover open(以完全覆盖的方式打开一个新的ActivityB--CoverActivity)
img

以对话框的形式打开ActivityB

点击第二个按钮 打开新的Activity - DialogActivity
- 启动ActivityA:ActivityA.onCreate()--->ActivityA.onStart()--->ActivityA.onResume();
img
- 以对话框的形式打开ActivityB的函数调用过程:
ActivityA.onPause()-->ActivityB.onCreate()-->ActivityB.onStart()-->ActivityB.onResume();
img


Activity的启动模式

Activity启动方式有四种,分别是:

可以根据实际的需求为Activity设置对应的启动模式,从而可以避免创建大量重复的Activity等问题。

设置Activity的启动模式,只需要在AndroidManifest.xml里对应的标签设置android:launchMode属性,例如:

  1. <activity
  2. android:name=".ActivityName"
  3. android:launchMode="standard" />

下面是这四种模式的作用:
参考:http://blog.csdn.net/shinay/article/details/7898492

standard

默认模式,可以不用写配置。在这个模式下,都会默认创建一个新的实例。因此,在这种模式下,可以有多个相同的实例,也允许多个相同Activity叠加。当用户单击多次后会生成很多相同的Activity,造成性能下降

例如:
若我有一个Activity名为A1, 上面有一个按钮可跳转到A1。那么如果我点击按钮,便会新启一个Activity A1叠在刚才的A1之上,再点击,又会再新启一个在它之上……
点back键会依照栈顺序依次退出。

singleTop

可以有多个实例,但是不允许多个相同Activity叠加。在每次启动ActivityA时,会首先检查Activity的栈顶是否已经存在ActivityA,如果存在,则重用栈顶的Activity, 不会让新的ActivityA再次入栈.但会首先让栈顶的ActivityA处于暂停状态(onPause()),之后会调用ActivityA的onNewIntent()方法,之后栈顶的ActivityA会再次处于运行状态(onResume()); 当用户多次单击后感觉不清楚

singleTask

只有一个实例。在同一个应用程序中启动他的时候,若Activity不存在,则会在当前task创建一个新的实例,若存在,则会把task中在其之上的其它Activity destory掉并调用它的onNewIntent方法。

singleInstance

只有一个实例,并且这个实例独立运行在一个task中,这个task只有这个实例,不允许有别的Activity存在。


课程总结和实验

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注