Android学习笔记38:Android四大组件之Activity

  Android应用程序的四大组件分别是Activity、Service、BroadcastReceiver和ContentProvider。本文将主要对Activity做一个较全面的总结,Service和BroadcaseReceiver也将在随后的博文中分别进行介绍。有关ContentProvider的使用方法可以参阅博文《Android学习笔记37:使用Content Providers方式共享数据》。

 

1.Activity注册

  Activity是Android中最常见的组件,每个Activity都相当于一个屏幕,为用户提供了进行交互的可视化界面。应用程序可以根据需要包含一个或多个Activity,这些Activity都继承自android.app包下的Activity类,并且这些Activity之间的运行是相互独立的。

  应用程序中使用到的所有Activity都需要在AndroidManifest.xml文件中进行注册。注册Activity时,需要使用<Activity></Activity>标签,该标签位于<application></application>中,具体位置如下:

 1   <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 2     package="com.example.android_datastorage_sqlite"
 3      android:versionCode="1"
 4      android:versionName="1.0" >
 5   
 6     <application
 7       android:icon="@drawable/ic_launcher"
 8        android:label="@string/app_name"
 9        android:theme="@style/AppTheme">
10   
11       <activity
12               android:name=".MainActivity"
13               android:label="@string/title_activity_main" >
14               <intent-filter>
15                   <action android:name="android.intent.action.MAIN" />
16                   <category android:name="android.intent.category.LAUNCHER" />
17               </intent-filter>
18           </activity>
19   
20       </application>
21   
22   </manifest>  

1.1 <Activity>标签的属性值

  在<Activity></Activity>标签中,有以下一些常用的属性值可以设置:

  (1)android:name,该属性值用于表示自定义的Activity子类名称,其值可以是子类的全称类名“com.example.android_datastorage_sqlite.MainActivity”,也可以以“.”开头省略掉应用程序的包名,后面直接加上子类的类名(即“.MainActivity”)。

  (2)android:process,该属性值用于表示Activity组件应该运行在哪个进程中,一般情况下不用设置该属性,所有的组件均运行在同一个进程中。如果该值以“:”开头将会为该Activity创建一个私有的新进程;如果该值以小写字母开头将会创建一个全局的新进程。

  (3)android:permission,该属性值用于指定启动该Activity所必须具有的权限。

  (4)android:screenOrientation,该属性值用于设置屏幕方向,可以选择的设置值有:unspecified(默认值,由系统来选择方向)、landecape(横向显示,宽度比高度大)、portrait(纵向显示,高度比宽度大)、user(使用用户当前首选的方向)、behind(使用与Activity堆栈中该Activity之下的那个Activity相同的方向)、sensor(显示的方向由设备的方向传感器来决定)、nosensor(屏幕的显示方向不会参照物理方向传感器)。

  (5)android:launchMode,该属性值用于设置Activity的启动模式,可以选择的设置值有:standard、singleTop、singleTask、singleInstance。

  (6)android:theme,该属性值用于设置Activity的主题模式。

1.2 <Activity>标签的内嵌标签

  在<Activity></Activity>标签中,可以内嵌以下两个标签:

  (1)<intent-filter></intent-filter>,该标签指明了Activity组件的过滤规则。

  (2)<meda-data>,该标签指明了额外的提供给Activity组件的数据值。

1.3不同包下的Activity注册方法

  当应用程序中包含多个Activity,并且这些Activity不在同一个包中时,注册Activity时需要做一点小小的改动。

  比如,在图1所示的工程中包含了3个Activity,且这3个Activity处于不同的包中。

图1 工程目录结构示意图

  那么,在注册AddDialogActivity和DeleteDialogActivity时,使用上述代码中和注册MainActivity一样的方法是行不通的。因为上述代码指定了package="com.example.android_datastorage_sqlite",所以可以使用android:name=".MainActivity"的方式注册MainActivity。但是很显然,AddDialogActivity和DeleteDialogActivity并不在包"com.example.android_datastorage_sqlite"中,所以我们应当使用android:name=".userOerate.AddDialogActivity"和android:name=".userOerate.DeleteDialogActivity"的方式来注册AddDialogActivity和DeleteDialogActivity组件。

 

2.Activity生命周期

  Activity的生命周期包含3个阶段,7个方法。具体可以参阅博文《Android学习笔记04:Activity及Activity生命周期》。这里便不再赘述了。

 

3.Activity内容的两种声明方式

  Activity显示内容有两种声明方式,一种是通过xml布局文件来声明,一种是将屏幕设置为某个继承自View类的对象。

3.1通过xml布局文件声明

  Activity的xml布局文件位于工程的res目录下的layout目录中,一个布局文件就相当于一个View容器,其中可以添加Android系统内置的View(比如Button、TextView等),也可以添加自定义的继承自View类的子类对象,甚至是View容器。

  同时,在xml布局文件还可以指定View对象在View容器中的排列方式(比如线性布局LinearLayout等)。

  通过xml布局文件将不同的View对象整合在一起确实非常方便,但是留给开发人员的自主性却不够。尤其是当进行游戏编程时,往往Android系统中自带的View对象并不能完全满足设计需求。在这种情况下,一般需要通过继承和扩展View类来开发自己想要的用户界面。

3.2通过View类的子类对象声明

  使用View类的子类对象作为Activity所要显示的内容,可以通过以下的两个步骤来实现:

  (1)编写一个继承自View类的MyView类,在MyView类中需要实现onDraw(Canvas canvas)方法。在该方法中通过操作Canvas对象,完成界面的绘制工作。

  (2)实现了界面的绘制之后,就可以在Activity中通过setContentView(View view)方法加载MyView对象,从而让绘制的界面显示出来。

以上两个步骤的具体实现方法,可以参阅博文《Android学习笔记09:Paint及Canvas的简单应用》。

 

4.Activity之间的通信

  Intent对象是组件之间通信的载体,组件之间进行通信就是一个个Intent对象在不断的传递。Intent对象不仅可以运行在相同的组件之间(如Activity之间的通信),也可以运行在不同的组件之间(如Activity与Service之间的通信)。

  对于Activity组件,Intent主要通过调用Context.startActivity()、Context.startActivityForResult()方法实现传递,其结果是启动一个新的Activity或者使当前的Activity开始新的任务。

  关于如何使用以上两个方法实现Activity之间的通信,可以参阅博文《Android学习笔记33:Intent介绍及Intent在Activity中的使用方法》。

 

5.保存Activity临时状态数据

  在Activity中提供了onSaveInstanceState()方法,用于当前Activity在系统未经你许可的情况下(比如处于暂停或停止状态的Activity,在系统资源极度匮乏时,有可能被杀死)被销毁时,对当前Activity中的临时状态数据进行保存。

  使用onSaveInstanceState(Bundle outState)方法,可以在Activity被杀掉之前将Activity的临时状态数据以键值对的形式存放到Bundle对象中,从而能够在再次调用OnCreate()方法时恢复Activity状态。

  如下的代码使用onSaveInstanceState()方法对EditText对象中的输入内容进行了保存,并在OnCreate()方法中对EditText对象中的数据进行了恢复。

 1     EditText mEditText;                            //EditText对象,用于输入内容
 2     private static final String KEY1 = "editTextValues";    //用于保存EditText对象内容的键
 3     private static final String TAG = "MainActivity";        //Log输出过滤器
 4     
 5     /*
 6      * Function  :    onCreate方法,Activity创建时调用
 7      * Author    :    博客园-依旧淡然
 8      */
 9     public void onCreate(Bundle savedInstanceState) {
10         super.onCreate(savedInstanceState);
11         setContentView(R.layout.activity_main);
12         mEditText = (EditText)this.findViewById(R.id.edittext);
13         
14         //如果Bundle对象中保存有所需对象的内容,则恢复该对象内容
15         if((savedInstanceState != null) && savedInstanceState.containsKey(KEY1)) {
16             mEditText.setText(savedInstanceState.getString(KEY1));
17         }
18         Log.i(TAG, "-->onCreate()");
19     }
20 
21     /*
22      * Function  :    onSaveInstanceState方法,销毁Activity时调用
23      * Author    :    博客园-依旧淡然
24      */
25     protected void onSaveInstanceState(Bundle outState) {
26         super.onSaveInstanceState(outState);
27         String editTextValues = mEditText.getText().toString();    //获取EditText对象内容
28         outState.putString(KEY1, editTextValues);    //以键值对的形式保存EditText对象内容
29         Log.i(TAG, "-->onSaveInstanceState()");
30     }

  需要注意的一点是,onSaveInstanceState()方法并不是总会被调用的,只有系统为了节省内存资源而强制销毁Activity时才会调用,所以应当仅仅通过重写onSaveInstanceState()方法来保存一些临时数据,而不是持久数据。要保存持久数据,应该使用onPause()方法。

 

6.Activity的主题模式

  上面已经提到,通过设置<Activity></Activity>标签下的android:theme属性值,可以设置Activity的主题模式。

  在Android系统中预设了以下一些主题模式:

  (1)android:theme="@android:style/Theme.Dialog",将一个Activity显示为对话框模式 

  (2)android:theme="@android:style/Theme.NoTitleBar",不显示应用程序标题栏 

  (3)android:theme="@android:style/Theme.NoTitleBar.Fullscreen",不显示应用程序标题栏,且全屏显示该Activity 

  (4)android:theme="@android:style/Theme.Light",将Activity的背景设置为白色 

  (5)android:theme="@android:style/Theme.Light.NoTitleBar",将Activity的背景设置为白色,且不显示应用程序标题栏  

  (6)android:theme="@android:style/Theme.Light.NoTitleBar.Fullscreen",将Activity的背景设置为白色,不显示应用程序标题栏,且全屏显示该Activity  

  (7)android:theme="@android:style/Theme.Black",将Activity的背景设置为黑色 

  (8)android:theme="@android:style/Theme.Black.NoTitleBar",将Activity的背景设置为黑色,且不显示应用程序标题栏 

  (9)android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen",将Activity的背景设置为黑色,不显示应用程序标题栏,且全屏显示该Activity 

  (10)android:theme="@android:style/Theme.Wallpaper",以系统桌面做为Activity的背景

  (11)android:theme="@android:style/Theme.Wallpaper.NoTitleBar",以系统桌面做为Activity的背景,且不显示应用程序标题栏 

  (12)android:theme="@android:style/Theme.Wallpaper.NoTitleBar.Fullscreen",以系统桌面做为Activity的背景,不显示应用程序标题栏,且全屏显示该Activity 

  比如,我们可以通过设置android:theme="@android:style/Theme.Dialog",将一个Activity仿造成对话框Dialog的样子,如图2所示。

图2 对话框模式的Activity

posted @ 2013-04-21 22:58  依旧淡然  阅读(2236)  评论(0编辑  收藏  举报