《Android应用开发揭秘》连载3

《Android应用开发揭秘》

 

Android应用开发揭秘(国内首本基于Andriod 2.0的经典著作,5大专业社区一致鼎力推荐!)
 
书名:Android应用开发揭秘
作者:杨丰盛
出版社:机械工业出版社
ISBN:9787111291954
出版日期:2010 年3月(1版2次)
开本:16
页码:515
版次:1-2
定价:69元
豆瓣网讨论地址: http://www.douban.com/subject/4200822/
China-pub预订地址: http://www.china-pub.com/196305
 
 
第二部分 基础篇
 
第3章  Android程序设计基础
 
通过上一章的学习,我们对Eclipse+ADT开发流程有了初步的认识和了解,对初学者来说,这一章的内容比较繁琐,但是又必须掌握,这也是进行Android开发必须经过的第一步,有了这个基础,我们下面将进行正式开始Android应用程序设计。
 
3.1  Android程序框架
上一章我们建立了HelloAndroid项目,代码是由ADT插件自动生成的,我们没有对其进行编码,所以没有对其框架进行分析。其实每一个平台都有自己的结构框架,比如我们在最初学习Java或者C/C++时,第一个程序总是main函数,以及文件类型和存储方式等。这一节将对Android平台的目录结构、文件类型及其负责的功能和Android平台的main 函数进行剖析。
 
3.1.1  Android项目目录结构
有了前面两章的基础,现在我们再来打开上一章建立的HelloAndroid项目,分析其项目目录结构,对Android项目进一步地深入了解。首先启动Eclipse,展开“Package Explorer”导航器中的“HelloAndroid”项目,如图3-1所示。

1
 
 图3-1 HelloAndroid项目
 
与一般的Java项目一样,src文件夹是项目的所有包及源文件(.java),res文件夹中则包含了项目中的所有资源,比如:程序图标(drawable)、布局文件(layout)、常量(values)等。下面来介绍其他Java项目中没有的的gen文件夹中的R.java文件和每个Android项目都必须有的AndroidManfest.xml文件。
 
*  R.java是在建立项目时自动生成的,这个文件是只读模式,不能更改,R.java文件是定义该项目所有资源的索引文件。先来看看HelloAndroid项目的R.java文件,如代码清单3-1所示。
 
代码清单3-1  第2章/HelloAndroid/gen/com/yarin/Android/HelloAndroid/R.java
package com.yarin.Android.HelloAndroid;
public final class R {
    public static final class attr {
    }
    public static final class drawable {
        public static final int icon=0x7f020000;
    }
    public static final class layout {
        public static final int main=0x7f030000;
    }
    public static final class string {
        public static final int app_name=0x7f040001;
        public static final int hello=0x7f040000;
    }
}
 
可以看到这里定义了很多常量,这些常量的名字都与res文件夹中的文件名相同,这再次证明了R.java文件中所存储的是该项目所有资源的索引。有了这个文件,可以很快地找到要使用的资源,由于这个文件不能手动编辑,所以当在项目中加入了新的资源时,只需要刷新一下该项目,R.java文件便自动生成了所有资源的索引。
 
*  AndroidManfest.xml文件则包含了该项目中所使用的Activity、Service、Receiver,我们先来打开HelloAndroid项目中的AndroidManfest.xml文件,如代码清单3-2所示。
 
代码清单3-2  第2章/HelloAndroid/AndroidManfest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.yarin.Android.HelloAndroid"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".HelloAndroid"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-sdk android:minSdkVersion="5" />
</manifest>
 
代码清单3-2中,itent-filters描述了Activity启动的位置和时间。每当一个Activity(或者操作系统)要执行一个操作时,它将创建出一个Intent的对象,这个Intent对象能承载的信息可描述你想做什么,你想处理什么数据,数据的类型,以及一些其他信息。而Android则会和每个Application所暴露的intent-filter的数据进行比较,找到最合适Activity来处理调用者所指定的数据和操作。下面我们来仔细分析AndroidManfest.xml文件,如表3-1所示。
 
表3-1  AndroidManfest.xml分析
表3-1.1 表3-1.2

下面我们看看资源文件中一些常量的定义,如String.xml,如代码清单3-3所示。

代码清单3-3  第2章/HelloAndroid/String.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello World, HelloAndroid!</string>
    <string name="app_name">HelloAndroid</string>
</resources>
 
这个文件很简单,就定义了两个字符串资源,因此,我们可以在代码清单3-1中看到如下内容,即定义了“app_name”和“hello”两个常量,分别指向代码清单3-3中的两个字符串资源。
public static final class string {
    public static final int app_name=0x7f040001;
    public static final int hello=0x7f040000;
}
 
 那么如何在程序中使用我们所定义的这些资源呢?首先,通过Context的getResources实例化一个Resources对象,然后通过Resources的getString方法取得指定索引的字符串,代码如下:
Resources r = this.getContext().getResources();
String appname= ((String) r.getString(R.string.app_name));
String hello= ((String) r.getString(R.string.hello));
 
项目中所有使用的常量都可以通过这种XML文件的方式定义,比如,下面是我们通过XML文件定义的一些有关颜色的资源。
<?xml version="1.0" encoding="utf-8"?>
<resources>
 <color name="status_idle">#cccccc</color>
 <color name="status_done">#637a47</color>
 <color name="status_sync">#cc9900</color>
 <color name="status_error">#ac4444</color>
</resources>
 
现在来分析HelloAndroid项目的布局文件(layout),首先打开res->layout->main.xml文件,如代码清单3-4所示。

代码清单3-4  第2章/HelloAndroid/res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="@string/hello"
    />
</LinearLayout>
 
代码清单3-4中,有以下几个布局和参数。

 *  <LinearLayout>:线性版面配置,在这个标签中,所有元件都是按由上到下的排列排成的。
 *  android:orientation:表示这个介质的版面配置方式,其中“vertical”代表从上到下垂直布局,而“horizontal”代表从左到右水平布局。
*  android:layout_width:定义当前视图在屏幕上所占的宽度,fill_parent即填充整个屏幕。
*  android:layout_height:定义当前视图在屏幕上所占的高度,fill_parent即填充整个屏幕。
*  wrap_content:随着文字栏位的不同而改变这个视图的宽度或高度。

layout_weight 用于给一个线性布局中的多个视图的重要度赋值。所有视图都有layout_weight 值,默认为零,即需要显示多大的视图就占据多大的屏幕空间。如果值大于零,则将父视图中的可用空间分割,分割大小具体取决于每一个视图的layout_weight 值和该值在当前屏幕布局的整体 layout_weight 值,以及在其他视图屏幕布局的layout_weight 值中所占的比例。

在这里,布局中设置了一个TextView,用来配置文本标签Widget,其中设置的属性android:layout_width为整个屏幕的宽度,android:layout_height可以根据文字来改变高度,而android:text则设置了这个TextView要显示的文字内容,这里引用了@string中的hello字符串,即String.xml文件中的hello所代表的字符串资源。hello字符串的内容“Hello World, HelloAndroid!”就是我们在HelloAndroid项目运行时看到的字符串。

最后,我们来分析HelloAndroid项目的主程序文件HelloAndroid.java,如代码清单3-5所示。

代码清单3-5  第2章/HelloAndroid/src/com/yarin/Android/HelloAndroid/HelloAndroid.java
...
 public void onCreate(Bundle savedInstanceState)
 {
  super.onCreate(savedInstanceState);
  /* 设置Activity要显示的布局为(R.layout.main) */ 
  setContentView(R.layout.main);
 }
...
 
主程序HelloAndroid类继承自Activity类,重写了void onCreate(Bundle savedInstanceState)方法。在onCreate方法中通过setContentView(R.layout.main)设置Activity要显示的布局文件(/layout/main.xml)。

到这里,是不是明白了为什么我们在创建项目时没有进行编码就可以直接运行程序呢?当然,这也是Android开发的特点,这样可以很轻松地将代码和UI分开,在国际化和程序维护方面有着巨大的作用。如果你的Android程序需要适应国际化,比如说多国语言等问题,那么就可以定义不同语言的UI布局,在程序装载时调用不同的布局。而且,如果我们需要修改UI的一些问题,就不必查看代码了,直接更改这些布局文件即可,是不是很方便?当然,这需要开发者在开发时使用这种MVC框架,尽量减少使用“硬编码”。笔者个人建议使用这种框架。

3.1.2  Android应用解析
上面我们了解了Android应用程序的目录结构和其中每个文件的功能,要进行应用开发,还需要对Android应用构造进行深入分析。Android应用程序由4个模块构造而成:Activity,Intent,Content Provider,Service。

当然,也不是每个Android应用程序都必须由这4部分组成,可以根据开发者需求进行组合,比如上面建立的HelloAndroid项目就只使用了Activity这一个模块。但是,任何一个应用程序都必须在AndroidManfest.xml文件中声明使用到的这些模块。

1.Activity
Activity是最基本的模块,我们在HelloAndroid项目中已经使用过。我们称之为“活动”,在应用程序中,一个Activity通常就是一个单独的屏幕。每一个活动都被实现为一个独立的类,并且从活动基类中继承而来,活动类将会显示由视图控件组成的用户接口,并对事件作出响应。例如HelloAndroid项目中的HelloAndroid.java即继承了Activity类。大多数的应用都是由多个Activity显示组成,例如,对一个文本信息应用而言,第一个屏幕用来显示发送消息的联系人列表,第二个屏幕用来写文本消息和选择收件人,第三个屏幕查看消息历史或者消息设置操作等。

这里的每一个屏幕就是一个活动,很容易实现从一个屏幕到一个新的屏幕,并且完成新的活动。当一个新的屏幕打开后,前一个屏幕将会暂停,并保存在历史栈中。用户可以返回到历史栈中的前一个屏幕,当屏幕不再使用时,还可以从历史栈中删除。

简单理解,Activity代表一个用户所能看到的屏幕,主要用于处理应用程序的整体性工作,例如,监听系统事件(按键事件、触摸屏事件等),为用户显示指定的View,启动其他Activity等。所有应用的Activity都继承于android.app.Activity类,该类是Android提供的基层类,其他的Activity继承该父类后,通过父类的方法来实现各种功能,这种设计在其他领域也较为常见。

2.Intent
Android用Intent这个特殊类实现在Activity与Activity之间的切换。Intent类用于描述应用的功能。在Intent的描述结构中,有两个最重要的部分:动作和动作对应的数据。典型的动作类型有MAIN、VIEW、PICK、EDIT等,而动作对应的数据则以URI的形式表示。例如,要查看一个人的联系方式,需要创建一个动作类型为VIEW的Intent,以及一个表示这个人的URI。

通过解析各种Intent,从一个屏幕导航到另一个屏幕是很简单的。当向前导航时,Activity将会调用startActivity(IntentmyIntent)方法。然后,系统会在所有已安装的应用程序中定义的IntentFilter中查找,找到最匹配myIntent的Intent对应的Activity。新的Activity接收到myIntent的通知后,开始运行。当startActivity方法被调用时,将触发解析myIntent的动作,该机制提供了两个关键好处:

*  Activity能够重复利用从其他组件中以Intent形式产生的请求。
*  Activity可以在任何时候被具有相同IntentFilter的新的Activity取代。

下面我们举例说明两个Activity之间的切换。运行效果:当应用程序启动时显示布局main.xml,如图3-2所示,当点击“切换”按钮时,屏幕显示布局main2.xml,如图3-3所示,再点击“切换”按钮,又回到如图3-2所示界面。就这样通过Intent完成了两个Activity之间的切换。
            
2    3
 
                 图3-2  Activity01                              图3-3  Activity02

下面我们来分析一下代码的具体实现,我们知道该项目是由两个Activity构成,在这两个Activity中分别显示了一个文本标签和一个按钮,关于界面的布局会在本书第4章进行详细讲解,要实现两个Activity的跳转,我们可以将要跳转的Activity类名绑定到Intent对象中,然后通过startActivity方法激活Intent对象中所指定的Activity。关键代码如代码清单3-6所示。

代码清单3-6  第3章/Examples_03_01/src/com/yarin/android/Examples_03_01/Activity01.java
/* 监听button的事件信息 */
button.setOnClickListener(new Button.OnClickListener() {
 public void onClick(View v)
 {
  /* 新建一个Intent对象 */
  Intent intent = new Intent();
  /* 指定intent要启动的类 */
  intent.setClass(Activity01.this, Activity02.class);
  /* 启动一个新的Activity */
  startActivity(intent);
  /* 关闭当前的Activity */
  Activity01.this.finish();
 }
});
 
然后,我们要从Activity02跳转到Activity01时,就只是需要在Activity02.java中使用同样的方法返回Activity01中。大家可以参考本书所附代码:第3章/Examples_03_01/src/com/yarin/android/
Examples_03_01/ Activity02.java。值得注意的是,该项目中我们使用了两个Activity,每一个Activity都需要在AndroidManifest.xml文件中进行声明,声明方法如代码清单3-7所示。

代码清单3-7  第3章/Examples_03_01/AndroidManifest.xml
<activity android:name=".Activity01"
          android:label="@string/app_name">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
<activity android:name="Activity02"></activity>
    
 
如果希望Android应用能够对外部事件(如当电话呼入时,或者数据网络可用时,或者到了晚上时)做出响应,可以使用IntentReceiver。虽然IntentReceiver在感兴趣的事件发生时会使用NotificationManager通知用户,但它并不能生成UI。IntentReceiver在AndroidManifest.xml中注册,但也可以在代码中使用Context.registerReceiver()进行注册。当IntentReceiver被触发时,应用不必对请求调用IntentReceiver,系统会在需要时启动应用。各种应用还可以通过使用Context.broadcastIntent()将它们自己的IntentReceiver广播给其他应用。

3.Content Provider
Android应用能够将它们的数据保存到文件和SQLite数据库中,甚至是任何有效的设备中。当想将应用数据与其他的应用共享时,Content Provider就可以发挥作用了。因为Content Provider类实现了一组标准的方法,能够让其他的应用保存或读取此内容提供器处理的各种数据类型。

数据是应用的核心。在Android中,默认使用鼎鼎大名的SQLite作为系统数据库。但是在Android中,使用方法有点不一样。在Android中,每一个应用都运行在各自的进程中,当一个应用需要访问其他应用的数据时,也就是数据需要在不同的虚拟机之间传递,这样的情况操作起来可能有些困难(正常情况下,不能读取其他应用的db文件),Content Provider正是用来解决在不同的应用包之间共享数据的工具。

在Android中,Content Provider是一个特殊的存储数据的类型,它提供了一套标准的接口用来获取和操作数据。并且,Android自身也提供了现成的Content Provider:Contacts、Browser、CallLog、Settings、MediaStore。应用可以通过唯一的ContentResolver界面来使用具体的某个Content Provider,然后就可以用ContentResolver提供的方法来使用你需要的Content Provider了。其中,ContentResolver提供的方法包括query()、insert()、update()等。要使用这些方法,还会涉及URI。你可以将它理解成string形式的Content Provider的完全路径。

下面我们通过一个例子来学习Content Provider的使用,该例子主要实现通过Content Provider获得电话本中的数据,然后显示到一个TextView中,在运行程序之前我们先看看电话本中存储的电话号码,如图3-4所示,然后再运行程序看看我们获得的数据,如图3-5所示,并看看我们通过Content Provider获得的数据是否正确。
          
4    5
 
               图3-4  电话本数据                  图3-5  通过ContentProvider获得电话本数据

下面我们来分析一下如何实现通过ContentProvider取得电话本的数据,首先通过getContentResolver方法来取得一个ContentResolver对象,然后通过其query方法查询出符合标准的电话本记录,最后将这些数据都显示在一个TextView中即可,如代码清单3-8所示。

代码清单3-8  第3章/Examples_03_02/src/com/yarin/android/Examples_03_02/Activity01.java
public class Activity01 extends Activity
{
 public void onCreate(Bundle savedInstanceState)
 {
  TextView tv = new TextView(this);
  String string = "";  
  super.onCreate(savedInstanceState); 
  //得到ContentResolver对象
 ContentResolver cr = getContentResolver();  
 //取得电话本中开始一项的光标
 Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null,
 null, null);
 //向下移动光标
 while(cursor.moveToNext()) 
 { 
  //取得联系人名字
  int nameFieldColumnIndex = cursor.getColumnIndex(PhoneLookup.
  DISPLAY_NAME);     
  String contact = cursor.getString(nameFieldColumnIndex); 
  //取得电话号码
  int numberFieldColumnIndex = cursor.getColumnIndex(PhoneLookup.
  NUMBER);    
  String number = cursor.getString(numberFieldColumnIndex);
  
  string += (contact+":"+number+"/n");
 }
 cursor.close();
  //设置TextView显示的内容
  tv.setText(string);
  //显示到屏幕
  setContentView(tv);
 }
}
 
前面强调过,要使用这些模块,需要在AndroidManifest.xml声明,本例中我们使用了读取联系人的API,因此,声明方式如下所示:
<uses-permission 
 android:name="android.permission.READ_CONTACTS">
 </uses-permission>
 
4.Service
Service即“服务”的意思,既然是服务,那么Service将是一个生命周期长且没有用户界面的程序。比如一个正在从播放列表中播放歌曲的媒体播放器,在这个媒体播放器应用中,应该会有多个Activity,让使用者可以选择歌曲并播放歌曲。然而,音乐重放这个功能并没有对应的Activity,因为使用者会认为在导航到其他屏幕时音乐应该还在播放。在这个例子中,媒体播放器这个Activity会使用Context.startService()来启动一个Service,从而可以在后台保持音乐的播放。同时,系统也将保持这个Service一直执行,直到这个Service运行结束。另外,还可以通过使用Context.bindService()方法连接到一个Service上(如果这个Service当前还没有处于启动状态,则将启动它)。当连接到一个Service之后,还可用Service提供的接口与它进行通信。以媒体播放器为例,我们还可以执行暂停、重播等操作。

下面通过一个例子来学习Service的使用,该例子通过Service来播放一首MP3,如图3-6所示。当用户点击“开始”按钮,音乐开始播放;点击“停止”按钮,停止音乐播放。当然,这里需要在资源文件中添加一首MP3歌曲,如图3-7所示。

要实现音乐的播放,需要在界面中放置两个按钮,用来控制音乐的播放和停止。而我们的音乐播放是通过一个服务来实现的,所以我们可以通过startService和stopService方法来开启和停止这个播放音乐的服务,如代码清单3-9所示。
   
6      7
         
               图3-6  使用Service播放音乐                       图3-7  test.mp3

代码清单3-9  第3章/Examples_03_03/src/com/yarin/android/Examples_03_03/ Activity01.java
//开始按钮
private OnClickListener start = new OnClickListener()
{
    public void onClick(View v)
    {   
        //开启Service
        startService(new Intent("com.yarin.Android.MUSIC"));
    }
};
//停止按钮
private OnClickListener stop = new OnClickListener()
{
    public void onClick(View v)
    {
            //停止Service
        stopService(new Intent("com.yarin.Android.MUSIC"));       
    }
};
 
下面是该例子的核心内容。如何通过Service来播放音乐,其实也很简单,首先创建一个MusicService继承自Service,然后通过start和stop方法来控制音乐的播放,如代码清单3-10所示。具体实现请参见本书所附代码:第3章/Examples_03_03。

代码清单3-10  第3章/Examples_03_03/src/com/yarin/android/Examples_03_03 /MusicService.java
public class MusicService extends Service
{
 //MediaPlayer对象
 private MediaPlayer player;
 public IBinder onBind(Intent arg0)
 {
  return null;
 }
 public void onStart(Intent intent, int startId)
 {
  super.onStart(intent, startId);
  //这里可以理解为装载音乐文件
  player = MediaPlayer.create(this, R.raw.test);
  //开始播放
  player.start();
 }
 public void onDestroy()
 {
  super.onDestroy();
  //停止音乐—停止Service
  player.stop();
 }
}
 
我们使用Service时同样需要在AndroidManifest.xml中声明,声明方式如代码清单3-11所示。

代码清单3-11  第3章/Examples_03_03 /AndroidManifest.xml
<service android:name=".MusicService">
    <intent-filter>
        <action android:name="com.yarin.Android.MUSIC" />
        <category android:name="android.intent.category.default" />
    </intent-filter>
</service>   
 
3.2  Android的生命周期
在前面的几个例子中,我们发现所有继承自Activity的类都重写了onCreate方法,程序运行就会自动进入这个方法。其实Activity类中还有很多类似于onCreate的方法,比如onStart、onResume、onPause、onDestroy等,而这些方法都是系统自动调用,从名字上大概就可以看出这是一些关于生命周期的方法,那么这些方法被调用的先后顺序是怎样的呢?Android应用的生命周期又是如何呢?下面通过一个例子来进一步分析。

当应用程序启动时,进入如图3-8所示的Activity01界面,此时,点击“Activity02”按钮,进入Activity02界面,如图3-9所示。再点击“Activity01”按钮,返回Activity01界面,最后点击“Exit”按钮退出整个应用程序。
        
8         9
 
               图3-8  Activity01界面                        图3-9  Activity02界面

我们在这些类似于onCreate的方法中都加入了log函数,输出不同的信息,以便我们能更好地跟踪程序运行的过程,具体实现参见本书所附代码:第3章/Examples_03_04。

首先,我们需要在程序启动所默认的第一个界面中,加入一些Log函数,用于显示和输出Log信息,以帮助我们分析程序的执行流程,如代码清单3-12所示。

代码清单3-12  第3章/Examples_03_04/src/com/yarin/android/Examples_03_04 /Activity01.java
public class Activity01 extends Activity
{
 private static final String TAG = "Activity01";
 public void onCreate(Bundle savedInstanceState)
 {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  Log.v(TAG, "onCreate");
  
  Button button1 = (Button) findViewById(R.id.button1);
  /* 监听button的事件信息 */
  button1.setOnClickListener(new Button.OnClickListener() {
   public void onClick(View v)
   {
    /* 新建一个Intent对象 */
    Intent intent = new Intent();
    /* 指定intent要启动的类 */
    intent.setClass(Activity01.this, Activity02.class);
    /* 启动一个新的Activity */
    startActivity(intent);
    /* 关闭当前的Activity */
    Activity01.this.finish();
   }
  });
  /******************************/
  Button button3 = (Button) findViewById(R.id.button3);
  /* 监听button的事件信息 */
  button3.setOnClickListener(new Button.OnClickListener() {
   public void onClick(View v)
   {
    /* 关闭当前的Activity */
    Activity01.this.finish();
   }
  });
 }
 public void onStart()
 {
  super.onStart();
  Log.v(TAG, "onStart");
 }
 
 public void onResume()
 {
  super.onResume();
  Log.v(TAG, "onResume");
 }
 
 public void onPause()
 {
  super.onPause();
  Log.v(TAG, "onPause");
 }
 
 public void onStop()
 {
  super.onStop();
  Log.v(TAG, "onStop");
 }
 public void onDestroy()
 {
  super.onDestroy();
  Log.v(TAG, "onDestroy");
 }
 public void onRestart()
 {
  super.onRestart();
  Log.v(TAG, "onReStart");
 }
 
}
 
在第二个界面中,同第一个界面一样,加入一些可以区分的不同的Log信息。

同样需要在AndroidManifest.xml文件中声明所使用的两个Activity模块,如代码清单3-13所示。具体实现请参见本书所附代码:第3章/Examples_03_04。

代码清单3-13  第3章/Examples_03_04/AndroidManifest.xml
<activity android:name=".Activity01"
          android:label="@string/app_name">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
<activity android:name="Activity02"></activity>
 
当在Debug该项目时,切换到DDMS标签即可以看到所打印出来的Log信息,这样就可以很清楚地分析程序的运行过程。
当程序第一次启动时,打印的Log信息如图3-10所示。我们看到程序的运行顺序为:Activity01 onCreate→Activity01 onStart →Activity01 onResume。这里我们可以看到,当一个Activity启动时,不是“创建”之后“开始”就完了,而是要经过“创建”,然后“开始”,最后“重绘”。

10
 
图3-10  第一次启动进入Activity01界面

当我们进入Activity02界面时,打印出的Log信息如图3-11所示。我们看到程序的运行顺序为:Activity01 onPause→Activity02 onCreate→Activity02 onStart→Activity02 onResume→Activity01 onStop→Activity01 onDestroy。这里我们看到,当程序从Activity01界面进入Activity02界面时,并不是马上将Activity01销毁,而是待Activity02启动之后将Activity01停止并销毁。

当我们返回Activity01界面时,打印出的Log信息如图3-12所示。我们看到程序的运行顺序为:Activity02 onPause→Activity01 onCreate→Activity01 onStart→Activity01 onResume→Activity02  onStop→Activity02 onDestroy。这里我们看到,当程序从Activity02界面返回Activity01界面时,并不是马上将Activity02销毁,而是待Activity01启动之后将Activity02停止并销毁。
     
11   12
 
             图3-11  进入Activity02界面                      图3-12  返回Activity01界面

最后,当我们点击“Exit”按钮退出应用程序时,打印出的Log信息如图3-13所示。这里我们看到程序的运行顺序为:Activity01 onPause→Activity01 onStop→Activity01 onDestroy。这里我们看到当一个应用程序在退出时,并不是马上“停止”且“销毁”,而是经过“暂停”,到“停止”,然后再“销毁”。

13
 
图3-13  退出应用程序

通过上面的例子,我们得出Android应用程序的生命周期如图3-14所示。

14
 
图3-14  Android应用的生命周期

3.3  Android程序UI设计
在前面章节的例子中,我们已经接触了一些UI控件,比如TextView、Button等,其实这里所说的UI就是在我们所说的布局文件,UI是一个应用程序的脸面,一个应用程序要想受用户喜爱, UI可不能差。自从Android SDK 1.0_r2版本开始,ADT提供了UI预览的功能。现在我们只需要打开一个Android项目的“/res/ layout/main.xml”并右键单击,依次选择“Open With”→“Android layout Editor”菜单命令,或者直接双击main.xml文件,即可以切换到UI设计界面,如图3-15所示。

15
 
图3-15  Android Layout Editor命令

左边的Layouts标签的内容则是一些线性布局,可以使用它轻松地完成对布局的排版,比如横向或者纵向布局。Views标签则是一些UI控件,可以将这些控件直接拖动到右边的窗口进行编辑,如图3-16所示。

16
 
图3-16  Android Layout Editor

当然,还可以点击右下角的main.xml标签来切换到XML编辑器,对代码进行编排,如图3-17所示。将这些功能配合起来使用,基本可以满足开发者需求。
除了这个还不算太成熟的UI编辑器之外,笔者曾经使用过一个第三方的工具DroidDraw,DroidDraw是一个公开了源代码的UI设计器,可以根据自己的开发需要进行修改。www. DroidDraw.org提供了在线使用DroidDraw的功能,当然也可以下载到本地来进行编辑,下载地址: http://code.google.com/p/droiddraw/

17
 
图3-17  XML编辑器

DroidDraw的功能比较强大,可以直接拖动控件到窗口,然后设置其属性、参数等,这样便可以随心所欲地设计自己需要的UI,然后点击“Generate”按钮即可生成出对应的布局代码,同时也可以点击“Load”按钮来载入已经编辑好的布局文件,如图3-18所示。

18
 
图3-18  DroidDraw操作界面
 
3.4  小结
本章主要介绍了Android应用程序框架及其生命周期,以及UI设计。首先彻底分析了上一章的HelloAndroid项目,从其项目目录结构、文件功能等方面分析了Android应用程序的基本框架,其次逐一分析了构成Android应用程序的4个模块(Activity、Intent、Content Provider、Service),分别通过示例程序演示了其功能的运用。接着通过一个示例程序验证了Android应用程序的运行流程,从而得出Android应用程序的生命周期流程图。最后介绍了两个有关UI设计的工具,使得程序界面更加漂亮。
相信通过本章的学习,你已经开始“喜欢”上Android了,有你的这份热情和执着,加上每一章的示例,让你边学边做,理论加实践,轻轻松松学会Android应用开发。加油吧!后面的内容更精彩。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
作者简介   杨丰盛,Android应用开发先驱,对Android有深入研究,实战经验极其丰富。精通Java、C、C++等语言,专注于移动通信软件开发,在机顶盒软件开发和MTK平台软件开发方面有非常深厚的积累。2007年获得中国软件行业协会游戏软件分会(CGIA)认证及国际游戏开发教育联合会国际认证。曾经领导和参与《三国群英传说》、《大航海传奇》、《美少女养成计划》等经典游戏的开发。 编辑本段 图书目录   前言   第一部分 准备篇   第1章 Android开发简介   1.1 Android基本概念   1.1.1 Android简介   1.1.2 Android的系统构架   1.1.3 Android应用程序框架   1.2 OMS介绍   1.2.1 OPhone介绍   1.2.2 Widget介绍   1.3 小结   第2章 Android开发环境搭建   2.1 Android开发准备工作   2.2 开发包及其工具的安装和配置   2.2.1 安装JDK和配置Java开发环境   2.2.2 Eclipse的安装与汉化   2.2.3 SDK和ADT的安装和配置   2.3 创建第一个Android项目——HeUoAndroid   2.3.1 创建HelloAndroid项目   2.3.2 运行HelloAndroid及模拟器的使用   2.3.3 调试HelloAndroid   2.4 小结   第二部分 基础篇   第3章 Android程序设计基础   3.1 Android程序框架   3.1.1 Android项目目录结构   3.1.2 Android应用解析   3.2 Android的生命周期   3.3 Android程序U设计   3.4 小结   第4章 用户界面开发   4.1 用户界面开发详解   4.1.1 用户界面简介   4.1.2 事件处理   4.2 常用控件应用   4.2.1 文本框(Textiew)   4.2.2 列表(ListView)   4.2.3 提示(T0ast)   4.2.4 编辑框(EditText)   4.2.5 单项选择(RadioGroup、RadioButton   4.2.6 多项选择(CheckBox)   4.2.7 下拉列表(Spinner)   4.2.8 自动提示(AutoComplete.TextⅥew)   4.2.9 日期和时间(DatePicker、TimePicker)   4.2.10 按钮(Button)   4.2.1l 菜单(Menu)   4.2.12 对话框(Dialog)   4.2.13 图片视图(ImageView)   4.2.14 带图标的按钮(ImageButton)   4.2.15 拖动效果(Gallery)   4.2.16 切换图片(hmgeSwilcher)   4.2.17 网格视图(GridView)   4.2.18 卷轴视图(ScrollView)   4.2.19 进度条(ProgressBar)   4.2.20 拖动条(SeekBar)   4.2.21 状态栏提示(Notification、NotificationManager)   4.2.22 对话框中的进度条(ProgressDialog)   4.3 界面布局   4.3.1 垂直线性布局   4.3.2 水平线性布局   4.3.3.相对布局(RelativeLayout)   4.3.4 表单布局(TableLayout)   4.3.5 切换卡(TabWidget)   4,4 小结   第5章 Android游戏开发   5.1 Android游戏开发框架   5.1.1 View类开发框架   5.1.2 SurfaceView类开发框架   5.2 Graphics类开发   5.5.1 Paint和Color类介绍   5.2.2 Canvas类介绍   5.2.3 几何图形绘制   5.2.4 字符串绘制   5.2.5 图像绘制   5.2.6 图像旋转   5.2.7 图像缩放   5.2.8 图像像素操作   5.2.9 Shader类介绍   5.2.10 双缓冲技术   5.2.11 全屏显示   5.2.12 获得屏幕属性   5.3 动画实现   5.3.1 Tween动画   5.3.2 Frame动画   5.3.3 GIF动画播放   5.4 小结   第6章 Android数据存储   6.1 Android数据存储初探   6.2 数据存储之Shared Preferences   6.3 数据存储之Files   6.4 数据存储之Network   6.5 Android数据库编程   6.5.1 SQLite简介   6.5.2 SQLite编程详解   6.5.3 SQLiteOpenHelper应用   6.6 数据共享(ContentProviders)   6.7 小结   第7 章多媒体开发   7.1 多媒体开发详解   7.1.1 Open Core   7.1.2 MediaPlayer   7.1.3 MediaRecorder   7.2 播放音乐   7.3 播放视频   7.4 录制歌曲   7.5 相机设置   7.6 闹钟设置   7.7 铃声设置   7.8 小结   第8章 网络与通信   8.1 网络通信基础   8.1.1 无线网络技术   8.1.2 Android网络基础   8.2 HTTP通信   8.2.1 HttpURLConnection接口   8.2.2 HttpClient接口   8.2.3 实时更新   8.3 Socket通信   8.3.1 Socket基础   8.3.2 Socket应用(简易聊天室)   8.4 网络通信的中文乱码问题   8.5 WebKit应用   8.5.1 WebKjt概述   8.5.2 WebView浏览网页   8.5.3 WebView与Javascript   8.6 WtFi介绍   8.7 蓝牙   8.8 小结   第9章 Android特色开发   9.1 传感器   9.2 语音识别   9.3 GoogleMap   9.3.1 GoogleMap概述   9.3.2 准备工作   9.3.3 GoogleMapAPI的使用   9.3.4 定位系统   9.4 桌面组件   9.4.1 快捷方式   9.4.2 实时文件夹   9.4.3 Widget开发   9.5 账户管理   9.6 小结   第三部分 实例篇   第10章 Android应用开发实例   10.1 情境模式   10.2 文件管理器   10.3 通讯录   10.4 音乐播放器   10.5 天气预报   10.6 个人地图   10.7 Widget日历   10.8 小结   第11 章Android游戏开发实例   11.1 手机游戏开发简介   11.2 游戏框架设计   11.3 地图设计   11.4 主角设计   11.5 图层管理器   11.6 游戏音效   11.7 游戏存档   11.8 小结   第四部分 高级篇   第12章 AndroidOpenGL开发基础   12.1 OpenGL简介   12.2 多边形   12.3 颜色   12.4 旋转   12.5 3D 空间   12.6 纹理映射   12.7 光照和事件   12.8 混合   12.9 小结   第13章 AndroidOpenGL综合应用   13.1 移动图像   13.2.3D 世界   13.3 飘动的旗帜   13.4 显示列表   13.5 雾   13.6 粒子系统   13.7 蒙版   13.8 变形   13.9 小结   第14章 游戏引擎实现   14.1 游戏引擎介绍   14.1.1 什么是引擎   14.1.2 引擎的进化   14.1.3 常见的游戏引擎   14.1.4 Android游戏引擎   14.2 游戏引擎结构   14.2.1 游戏引擎原理   14.2.2 游戏引擎定位   14.2.3 游戏引擎框架   14.3 游戏引擎设计   14.3.1 游戏引擎结构和功能设计   14.3.2 游戏引擎设计注意事项   14.4 游戏引擎实现   14.4.1 Activity类实现   14.4.2 流程控制和线程   14.4.3 游戏对象与对象管理   14.4.4 图形引擎   14.4.5 物理引擎   14.4.6 事件模块   14.4.7 工具模块   14.4.8 脚本引擎、音效模块、网络模块   14.5 小结   第15章 优化技术   15.1 优化的基本知识   15.1.1 如何书写出优秀代码   15.1.2 编程规范   15.2 程序性能测试   15.2.1 计算性能测试   15.2.2 内存消耗测试   15.3 初级优化   15.4 高级优化   15.5 Android高效开发   15.6 AndroidUI优化   15.7 其他优化   15.7.1 zipalign   15.7.2 图片优化   15.8 小结   第五部分 扩展篇   第16章 Android NDK开发   16.1 AndroidNDK简介   16.2 安装和配置NDK开发环境   16.2.1 系统和软件需求   16.2.2 NDK开发环境搭建   16.2.3 编译第一个NDK程序   16.3 AndroidNDK开发   16.3.1 JNI接口设计   16.3.2 使用C\C++实现本地方法   16.3 编译C\C++代码   16.4 AndroidNDK中使用0penGL   16.5小结   第17章 Android脚本环境   17.1 Android脚本环境简介   17.2 Android脚本环境安装   17.3如何编写Android脚本程序   17.4小结
Android应用开发揭秘   Windows操作系统的诞生成就了微软的霸主地位,也造就了PC时代的繁荣。然而,以Android和iPhone手机为代表   的智能移动设备的发明却敲响了PC时代的丧钟!移动互联网时代(3G时代)已经来临,谁会成为这些移动设备上的主   宰?毫无疑问,它就是Android——PC时代的Windows!   移动互联网还是一个新生的婴儿,各种移动设备上的操作系统群雄争霸!与Sym‘Dian、i P}lone OS、Wiridows Mobile   相比,Androjd有着天生的优势一完全开放和免费,对广大开发者和手机厂商而言,这是何等的诱人!此外,在Google   和以其为首的Android手机联盟的大力支持和推广下,Android不仅得到了全球开发者社区的关注,而且一大批世界一流   的手机厂商都已经或准备采用Android。   拥抱Android开发。拥抱移动开发的未来!   如果你在思考下面这些问题,也许本书就是你想要的!   Android开发与传统的J2ME开发有何相似与不同?   如何通过Shared Preferences、Files、Network和SQLite等方式高效实现Android数据的存储?又如何通过Content Providers轻松地实现Androld数据的共享?   如何使用Open Core、MediaPlayer、MediaRecorder方便快速地开发出包含音频和视频等流媒体的丰富多媒体应用?   如何利用Android 2.0新增的蓝牙特性开发包含蓝牙功能的应用?又如何使用蓝牙APL来完善应用的网络功能?   如何解决Android网络通信中的乱码问题?   在Android中如何使用语音服务和Google Map Apl? Android如何访问摄象头、传感器等硬件的APl?   如何时行Widget开发?如何用各种Android组件来打造漂亮的UI界面?   Android如何解析XML数据?又如何提高解析速度和减少对内存、CPU资源的消耗?   如何使用OpenGL ES在Android平台上开发出绚丽的3D应用?在Android平台上如何更好地设计和实现游戏引擎?   如何对Android应用进行优化?如何进行程序性能测试?如何实现UI、zipalign和图片优化?如何通过NDK利用C、C++以及通过ASE利用Python等脚本语言Android开发应用?   国内首本基于Android 2.0的经典著作,5大专业社区一致鼎力推荐!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值