zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    利用opengl画一个水波的曲面
    Eclipse 使用OpenGL
    Javascript学习过程(二)
    Workflow Learing
    YAWL设计实例
    YAWL使用方法
    ImageJ二次开发学习纪录之初步体会
    [LeetCode 660] Remove 9
    [LeetCode 1542] Find Longest Awesome Substring
    [LeetCode 879] Profitable Schemes
  • 原文地址:https://www.cnblogs.com/menlsh/p/3034699.html
Copyright © 2011-2022 走看看