Android中Activity组件详解

来源:互联网 发布:unity3d assetstore 编辑:程序博客网 时间:2024/04/30 05:39

Android中Activity组件详解

分类: Android 2183人阅读 评论(1) 收藏 举报
androidactionstringmanagerschemefilter

1.Activity 的生命周期

和J2ME的MIDlet一样,在Android中,Activity的生命周期交给系统统一管理。与MIDlet不同的是安装在Android中的所有的Activity都是平等的。

⑴Activity 的状态及状态间的转换
在 android 中,Activity拥有四种基本状态:
      ①Active/Runing一个新Activity启动入栈后,它在屏幕最前端,处于栈的最顶端,此时它处于可见并可和用户交互的激活状态。
      ②Paused当Activity被另一个透明或者Dialog 样式的Activity覆盖时的状态。此时它依然与窗口管理器保持连接,系统继续维护其内部状态,所以它仍然可见,但它已经失去了焦点故不可与用户交互。
      ③Stoped当Activity被另外一个Activity覆盖、失去焦点并不可见时处于Stoped状态。
      ④Killed Activity被系统杀死回收或者没有被启动时处于Killed状态。
当一个Activity实例被创建、销毁或者启动另外一个Activity时,它在这四种状态之间进行转换,这种转换的发生依赖于用户程序的动作。下图说明了Activity在不同状态间转换的时机和条件:

如上所示,Android 程序员可以决定一个 Activity 的“生”,但不能决定它的“死”,也就时说程序员可以启动一个 Activity,但是却不能手动的“结束”一个 Activity。当你调用 Activity.finish()方法时,结果和用户按下 BACK 键一样:告诉 Activity Manager 该 Activity 实例完成了相应的工作,可以被“回收”。随后 Activity Manager 激活处于栈第二层的 Activity 并重新入栈,同时原 Activity 被压入到栈的第二层,从 Active 状态转到 Paused 状态。例如:从 Activity1 中启动了 Activity2,则当前处于栈顶端的是 Activity2,第二层是 Activity1,当我们调用 Activity2.finish()方法时,Activity Manager 重新激活 Activity1 并入栈,Activity2 从 Active 状态转换 Stoped 状态,Activity1. onActivityResult(int requestCode, int resultCode, Intent data)方法被执行,Activity2 返回的数据通过 data参数返回给 Activity1。

⑵Activity 栈
Android 是通过一种 Activity 栈的方式来管理 Activity 的,一个 Activity 的实例的状态决定它在栈中的位置。处于前台的 Activity 总是在栈的顶端,当前台的 Activity 因为异常或其它原因被销毁时,处于栈第二层的 Activity 将被激活,上浮到栈顶。当新的 Activity 启动入栈时,原 Activity 会被压入到栈的第二层。一个 Activity 在栈中的位置变化反映了它在不同状态间的转换。Activity 的状态与它在栈中的位置关系如下图所示:

如上所示,除了最顶层即处在 Active 状态的 Activity 外,其它的 Activity 都有可能在系统内存不足时被回收,一个 Activity 的实例越是处在栈的底层,它被系统回收的可能性越大。系统负责管理栈中 Activity 的实例,它根据 Activity 所处的状态来改变其在栈中的位置。

⑶Activity生命周期

在 android.app.Activity类中,Android 定义了一系列与生命周期相关的方法,在我们自己的 Activity 中,只是根据需要复写需要的方法,Java 的多态性会保证我们自己的方法被虚拟机调用,这一点与 J2ME 中的 MIDlet 类似。

[java] view plaincopy
  1. public class OurActivity extends Activity {  
  2.     protected void onCreate(Bundle savedInstanceState);  
  3.   
  4.     protected void onStart();  
  5.   
  6.     protected void onResume();  
  7.   
  8.     protected void onPause();  
  9.   
  10.     protected void onStop();  
  11.   
  12.     protected void onDestroy();  
  13. }  

这些方法的说明如下:

       ①protected void onCreate(Bundle savedInstanceState)一个 Activity 的实例被启动时调用的第一个方法。一般情况下,我们都覆盖该方法作为应用程序的一个入口点,在这里做一些初始化数据、设置用户界面等工作。大多数情况下,我们都要在这里从 xml 中加载设计好的用户界面。例如:

[java] view plaincopy
  1. setContentView(R.layout.main);   

当然,也可从 savedInstanceState中读我们保存到存储设备中的数据,但是需要判断 savedInstanceState是否为 null,因为 Activity 第一次启动时并没有数据被存贮在设备中: 

[java] view plaincopy
  1. if(savedInstanceState!=null){   
  2.     savedInstanceState.get("Key");   
  3. }   

      ②protected void onStart()该方法在 onCreate() 方法之后被调用,或者在 Activity 从 Stop 状态转换为 Active 状态时被调用。

      ③protected void onResume()在Activity从Pause状态转换到Active状态时被调用。

      ④protected void onPause()在Activity从Active状态转换到Pause状态时被调用。

      ⑤protected void onStop()在 Activity 从 Active 状态转换到 Stop 状态时被调用。一般我们在这里保存 Activity 的状态信息。

      ⑥protected void onDestroy()在 Active 被结束时调用,它是被结束时调用的最后一个方法,在这里一般做些释放资源,清理内存等工作。

此外,Android 还定义了一些不常用的与生命周期相关的方法可用:

[java] view plaincopy
  1. protected void onPostCreate(Bundle savedInstanceState);   
  2. protected void onRestart();   
  3. protected void onPostResume();  

Android 提供的文档详细的说明了它们的调用规则。 

 

2.创建一个Activity

在 android 中创建一个 Activity 是很简单的事情,编写一个继承自 android.app.Activity的 Java 类并在 AndroidManifest.xml声明即可。下面是一个为了研究 Activity 生命周期的一个 Activity 实例:

[java] view plaincopy
  1. public class EX01 extends Activity {  
  2.     private static final String LOG_TAG = EX01.class.getSimpleName();  
  3.     @Override  
  4.     public void onCreate(Bundle savedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6.         setContentView(R.layout.main);  
  7.         Log.e(LOG_TAG, "onCreate");  
  8.     }  
  9.     @Override  
  10.     protected void onStart() {  
  11.         Log.e(LOG_TAG, "onStart");  
  12.         super.onStart();  
  13.     }  
  14.     @Override  
  15.     protected void onResume() {  
  16.         Log.e(LOG_TAG, "onResume");  
  17.         super.onResume();  
  18.     }  
  19.     @Override  
  20.     protected void onPause() {  
  21.         Log.e(LOG_TAG, "onPause");  
  22.         super.onPause();  
  23.     }  
  24.     @Override  
  25.     protected void onStop() {  
  26.         Log.e(LOG_TAG, "onStop");  
  27.         super.onStop();  
  28.     }  
  29.     @Override  
  30.     protected void onDestroy() {  
  31.         Log.e(LOG_TAG, "onDestroy ");  
  32.         super.onDestroy();  
  33.     }  
  34. }  

AndroidManifest.xml 中通过 <activity> 节点说明 Activity,将 apk 文件安装后,系统根据这里的说明来查找读取 Activity,本例中的说明如下:

[xhtml] view plaincopy
  1. <activity android:name=".EX01" android:label="@string/app_name">   
  2.      <intent-filter>   
  3.          <action android:name="android.intent.action.MAIN" />   
  4.          <category android:name="android.intent.category.LAUNCHER" />   
  5.      </intent-filter>   
  6.  </activity>  

 

3.启动另外一个Activity

Activity.startActivity()方法可以根据传入的参数启动另外一个 Activity:

[java] view plaincopy
  1. Intent intent =new Intent(CurrentActivity.this,OtherActivity.class);   
  2. startActivity(intent);   

当然,OtherActivity同样需要在 AndroidManifest.xml 中定义。

 

4.Activity之间通信

在 Android 中,不同的 Activity 实例可能运行在一个进程中,也可能运行在不同的进程中。因此我们需要一种特别的机制帮助我们在 Activity 之间传递消息。Android 中通过 Intent 对象来表示一条消息,一个 Intent 对象不仅包含有这个消息的目的地,还可以包含消息的内容,这好比一封 Email,其中不仅应该包含收件地址,还可以包含具体的内容。对于一个 Intent 对象,消息“目的地”是必须的,而内容则是可选项。

在上面的实例中通过 Activity. startActivity(intent)启动另外一个 Activity 的时候,我们在 Intent 类的构造器中指定了“收件人地址”。

如果我们想要给“收件人”Activity 说点什么的话,那么可以通过下面这封“e-mail”来将我们消息传递出去:

[java] view plaincopy
  1. Intent intent =new Intent(CurrentActivity.this,OtherActivity.class);  
  2. // 创建一个带“收件人地址”的 email   
  3. Bundle bundle =new Bundle();// 创建 email 内容  
  4. bundle.putBoolean("boolean_key"true);// 编写内容  
  5. bundle.putString("string_key""string_value");   
  6. intent.putExtra("key", bundle);// 封装 email   
  7. startActivity(intent);// 启动新的 Activity  

那么“收件人”该如何收信呢?在 OtherActivity类的 onCreate()或者其它任何地方使用下面的代码就可以打开这封“e-mail”阅读其中的信息:

[java] view plaincopy
  1. Intent intent =getIntent();// 收取 email   
  2. Bundle bundle =intent.getBundleExtra("key");// 打开 email   
  3. bundle.getBoolean("boolean_key");// 读取内容  
  4. bundle.getString("string_key");  

上面我们通过 bundle对象来传递信息,bundle维护了一个 HashMap<String, Object>对象,将我们的数据存贮在这个 HashMap 中来进行传递。但是像上面这样的代码稍显复杂,因为 Intent 内部为我们准备好了一个 bundle,所以我们也可以使用这种更为简便的方法: 

[java] view plaincopy
  1. Intent intent =new Intent(EX06.this,OtherActivity.class);   
  2. intent.putExtra("boolean_key"true);   
  3. intent.putExtra("string_key""string_value");   
  4. startActivity(intent);  

接收:

[java] view plaincopy
  1. Intent intent=getIntent();   
  2. intent.getBooleanExtra("boolean_key",false);   
  3. intent.getStringExtra("string_key");  

   

5.Activity的Intent Filter

Intent Filter 描述了一个组件愿意接收什么样的 Intent 对象,Android 将其抽象为android.content.IntentFilter 类。在 Android 的 AndroidManifest.xml 配置文件中可以通过 <intent-filter >节点为一个 Activity 指定其 Intent Filter,以便告诉系统该 Activity 可以响应什么类型的 Intent。
当程序员使用 startActivity(intent) 来启动另外一个 Activity 时,如果直接指定 intent 了对象的 Component 属性,那么 Activity Manager 将试图启动其 Component 属性指定的 Activity。否则 Android 将通过 Intent 的其它属性从安装在系统中的所有 Activity 中查找与之最匹配的一个启动,如果没有找到合适的 Activity,应用程序会得到一个系统抛出的异常。这个匹配的过程如下:

⑴Action匹配

Action 是一个用户定义的字符串,用于描述一个Android 应用程序组件,一个Intent Filter 可以包含多个Action。在AndroidManifest.xml的Activity定义时可以在其<intent-filter>节点指定一个Action列表用于标示Activity所能接受的“动作”,例如:

[xhtml] view plaincopy
  1. <intent-filter >   
  2. <action android:name="android.intent.action.MAIN" />   
  3. <action android:name="com.zy.myaction" />   
  4. ……  
  5. </intent-filter>   

如果我们在启动一个 Activity 时使用这样的 Intent 对象:

[java] view plaincopy
  1. Intent intent =new Intent();   
  2. intent.setAction("com.zy.myaction");  

那么所有的 Action 列表中包含了“com.zy.myaction”的 Activity 都将会匹配成功。
Android 预定义了一系列的 Action 分别表示特定的系统动作。这些 Action 通过常量的方式定义在 android.content. Intent中,以“ACTION_”开头。我们可以在 Android 提供的文档中找到它们的详细说明。

⑵URI数据匹配

一个Intent可以通过URI携带外部数据给目标组件。在<intent-filter>节点中,通过 <data/>节点匹配外部数据。
mimeType 属性指定携带外部数据的数据类型,scheme 指定协议,host、port、path 指定数据的位置、端口、和路径。如下:

[xhtml] view plaincopy
  1. <data android:mimeType="mimeType" android:scheme="scheme"   
  2.  android:host="host" android:port="port" android:path="path"/>  

如果在Intent Filter中指定了这些属性,那么只有所有的属性都匹配成功时URI数据匹配才会成功。 

⑶Category类别匹配

<intent-filter>节点中可以为组件定义一个Category类别列表,当Intent中包含这个列表的所有项目时Category类别匹配才会成功。

6.Activity的应用技巧

⑴全屏的Activity

要使一个 Activity 全屏运行,可以在其 onCreate()方法中添加如下代码实现:

[java] view plaincopy
  1. //隐藏标题栏    
  2. requestWindowFeature(Window.FEATURE_NO_TITLE);    
  3. // 隐藏状态栏    
  4. getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,    
  5.         WindowManager.LayoutParams.FLAG_FULLSCREEN);  

具体可参考这篇博文:Android设置全屏的方法 

⑵Activity定义为Dialog样式

可以在定义Activity的属性中添加

[xhtml] view plaincopy
  1. android :theme="@android:style/Theme.Dialog"  

即把Activity设置为Dialog样式;

[xhtml] view plaincopy
  1. android:theme="@android:style/Theme.Translucent"  

即把Activity设置为半透明的。  

0 0
原创粉丝点击