赵工的个人空间


专业技术部分转网页计算转业余爱好部分


 手持终端

首页 > 专业技术 > 手持终端 > Android系统基本架构
Android系统基本架构

Android本意指机器人,是由Google公司于2007年推出的基于Linux平台的开源操作系统,逐渐发展成流行的手机平台。Android是一个包括操作系统、中间件、用户界面和关键应用软件的移动设备软件集合。
Android系统从下到上分为4层:Linux内核、Android程序库及Android运行时库、Android应用程序框架、应用程序等。分层的好处是在使用下层提供的服务的同时也为上层提供统一的服务,屏蔽本层及下层的差异,当本层及下层发生了变化不会影响到上层。

ANDROID

1.Android系统层次结构:

1)Linux内核(Linux Kernel):
Android的核心服务依赖于Linux,例如安全、内存管理、进程管理、网络堆栈、启动模型等,也作为硬件和软件之间的抽象层,隐藏具体硬件细节人为上层提供统一的服务。Android还增加了内核的驱动程序,如显示驱动、蓝牙驱动、相机驱动、内存卡驱动、Binder IPC驱动、输入设备驱动、USB驱动、WIFI驱动、音频系统驱动、电源管理等,这些驱动程序为Android系统的运行提供基础性支持。
2)Android程序库(Libraries)
Android包含一个C/C++库的集合,以供Android系统的各个组件使用。核心库包括:
·系统C库:由BSD继承衍生的标准C系统函数库libc,调整为基于嵌入式Linux设备的库。
·媒体库:基于PacketVideo的OpenCORE,这些库支持播放和录制多种常见的音频和视频格式,以及多种媒体的编码/解码格式,包括MPEG-4、H.264、MP3、AAC、AMR、JPG、PNG。
·界面管理Surface Manager:显示子系统的管理器,管理访问显示子系统和无缝组合多个应用程序的二维和三维图形层。
·LibWebCore:新式的Web浏览器引擎,驱动Android浏览器和可嵌入的Web视图。
·SGL:Skia图形库,基于基本的2D图形引擎。
·3D libraries:基于OpenGL ES 1.0 APIs的实现,该库使用硬件3D加速或使用高度优化的3D软加速。
·FreeType:位图bitmap和矢量vector字体渲染。
·SOLite:所有应用程序都可以使用的强大而轻量级的关系数据库引擎。
3)Android运行时环境(Android Runtime):
在Linux内核层上还有一个Android运行层,包括Dalvik虚拟机及Java核心库,提供了Java编程语言核心库的大多数功能。Dalvik虚拟机是Android使用的Java虚拟机,每一个Android应用程序都是Dalvik虚拟机中的实例,运行在它们自己的进程中。Dalvik虚拟机设计成在一个设备中可以高效地运行多个虚拟机。Dalvik虚拟机可执行文件格式是.dex,是一种压缩格式,适合内存和处理器速度有限的系统。Dalvik虚拟机依赖于Linux内核提供的基本功能,如线程和底层内存管理。
大多数虚拟机包括JVM都是基于栈的,而Dalvik虚拟机则是基于寄存器的,基于栈的机器需要更多指令,而基于寄存器的机器指令更大。dex是一套工具,可以将Java的.class格式转换成.dex格式,一个.dex文件通常会有多个.class。由于.dex有时必须进行最佳化,会使文件大小增加1~4倍,以odex为后缀。
4)Android应用程序框架(Application Framework):
Application Framework通过提供开放的开发平台,使开发者能够访问核心应用程序所使用的API框架,这样使得组件的重用得以简化,任何应用程序都能发布它的功能且任何其他程序可以使用这些功能,从而使开发者可以编制及其丰富和新颖的应用程序,自由地利用设备硬件优势访问位置信息、运行后台服务、设置闹钟、向状态栏添加通知等。
每个应用程序其实是一组服务和系统,包括如下内容:
·视图View:丰富的、可扩展的视图集合,用来构建应用程序,包括列表Lists、网格Grids、文本框Textboxs、按钮Buttons,甚至是可嵌入的网页浏览器。
·内容提供器ContentProviders:使应用程序可以访问其他应用程序的数据,或共享自己的数据。
·资源管理器ResourceManager:提供对于非代码资源的访问,如本地化字符串、图形和布局文件。
·消息管理器NotificationManager:使得应用程序能够在状态栏显示自定义的提示信息。
·活动管理器ActivityManager:管理应用程序生命周期,并提供常用的导航回退功能。
5)Android应用程序和小部件:
Android装配一个核心应用程序集合,连同系统一起发布,这些应用程序包括电子邮件、客户端、SMS程序、日历、地图、浏览器、联系人和其他设置等。而所有应用程序都是用Java语言编写的,由用户开发的Android应用程序和Android核心应用程序是同一层次的。

2.Android工程文件的目录结构:

一个标准的Android应用程序的工程文件包含以下几大部分:
·src目录:用来存放项目中所有Java源文件,包含Activity。
·gen目录:包含R.java文件,由开发平台自动生成和维护,开发者不能手动修改,提供了Android的资源全局索引。
·libs目录:可以将开发中用到的第三方JAR包复制到其中。
·assets目录:主要用于放置音频、视频等多媒体文件,及html、JavaScript、数据库等文件。
·res目录:放置的是资源文件,drawable包含图片文件,layout包含布局文件,values目录里面主要包含字符串strings.xml、颜色colors.xml以及数组arrays.xml资源,还可以创建更多分类目录,如anim、menu、raw、xml等。目录中的所有资源文件会被R.java自动记录。
·AndroidManifest.xml.:应用的配置文件,需要声明所有用到的Activity、Service、Receiver等。
·android.jar:包含构建应用程序所需的Android SDK库

3.Android系统中的数据存储:

Android系统中,提供的存储方式包括SharedPreferences、文件存储、SQLite数据库存储、ContentProvider及网络方式5种。
1)SharedPreferences:
一种配置文件读/写方式,默认保存在应用程序目录data/<packagename>/shared_prefs下,通过方法getSharedPreferences(xx,0)来获取SharedPreferences对象进行读/写操作。
2)文件存储:
系统提供文件读写操作的API,例如,openFileInput、openFileOutput等。Android系统中,应用程序的数据是私有的,其他应用程序无法访问。
3)SQLite数据库存储:
通过继承SQLiteOpenHelper类,通过该类的CRUD接口来进行数据库操作。
4)内容提供器ContentProvider:
通过调用其他应用程序的数据接口来实现数据的读/写访问。
5)网络方式:
主要通过访问网络提供的网络服务接口实现数据的读写服务。通过java.net.*、Android.net.*来进行HTTP访问技术的封装,利用其下提供的HttpPost、DefaultHttpClient、HttpResponse等类提供的访问接口来实现具体的Web服务访问。

4.Android应用的基本组件:

Android应用基本组件包括Activity、Service、Broadcast Receiver、Content Provider和Intent。其中Activity表示一个可视化的用户界面,每一个Activity提供了一个可视区域,在这个区域可以放置各种Android组件,如按钮、图像、文本框等,利用这些View组件来实现应用程序与用户的交互;Service是没有用户界面在后台运行的应用,比如网络操作、文件操作等,其他程序可以与Service进行通信;Broadcast Receiver仅是接收广播公告并作出响应,许多广播源自系统,如电池电量、时区改变等,应用程序也可以发起广播。Content Provider可以将一个应用程序的指定数据集提供给其他应用程序,实现程序间数据通信和共享,这些数据可以存储在文件系统或SQLite数据库中,或其他存储方式;Intent可以在不同组件之间传递消息,即将一个组件的请求传给另一个组件,这是一种运行时绑定机制。

Activity是Android应用程序中最基本使用最频繁的组件,每个Activity都被定义为一个独立的类class,并且继承Android提供的android.app.Activity类。在Activity类中有一个onCreate事件方法,一般在其中对Activity进行初始化,使用setContentView方法设置Activity上显示的视图组件,参数一般为XML布局文件的资源ID。大多数应用程序根据需要都是由多个界面组成,因此必须包含多个Activity类,这些Activity可以通过一个Activity栈进行管理,栈顶的是正在运行的Activity。

Activity具有生命周期,包括运行状态、暂停状态、停止状态、终止状态。Activity从一个状态运行到另一个状态,改变时会执行相应的生命周期方法。Android的android.app.Activity类定义了Activity生命周期中所包含的所有方法,有7个。
这些Activity生命周期的事件回调函数会被Android系统自动调用,用户也可以重载这些事件回调函数来完成自己的操作。生命周期回调函数说明见下表:

函数

说明

下一个方法

onCreate

Activity启动后第一个被调用的函数,常用来进行初始化

onStart或onRestart

onStart

当Activity显示在屏幕上时,该函数被调用

onRestart或onResume

onRestart

当Activity从停止状态进入活动状态前,调用该函数

onResume

onResume

当Activity能与用户交互接受用户输入时,该函数被调用

onPause

onPause

当Activity进入暂停状态时,该函数被调用

onResume或onStop

onStop

当Activity进入停止状态时,该函数被调用

onStart或onDestroy

onDestroy

在Activity被终止前,即进入非活动状态前,该函数被调用

对于Activity全生命周期,事件回调函数的调用顺序为onCreate->onStart->onResume ->onPause->onStop->->onDestroy。调用onCreate分配资源,调用onStart将Activity显示在屏幕上,调用onResume获取屏幕焦点,调用onPause、onStop、onDestroy释放资源并销毁进程。

Avtivity还有可见生命周期,从onStart开始到onStop结束,这段时间内Activity显示在屏幕上,需要保持显示给用户的UI数据和资源等,但有可能不在前台而不能与用户交互。Activity的前台生命周期是从onResume到onPause,此时该Activity处于所有Activity的最前面,能够与用户交互。

5.Android的布局管理:

Layout用于管理组件的布局格式,组织界面中组件的呈现方式。Android提供了多种布局,一般采用XML文件方式,将布局界面的代码和逻辑控制的Java代码分离开。在程序中通过setContentView(R.layout.xxxx)方法将布局呈现在Activity中,这是一种推荐的方式。

1)线性布局LinearLayout:

LinearLayout布局中子元素之间成线性排列,即在某一方向上顺序排列,有水平排列和垂直排列两种方式,对应代码为android:orientation="horizontal"和android:orientation="vertical"。LinearLayout支持的属性有:

属性

描述

android:baselineAligned

设置为false,将会阻止该布局管理器与它的子元素的基线对齐

android:divider

设置垂直布局时按钮之间的分隔条

android:gravity

设置对齐方式

android:orientation

设置排列方式,有horizontal、vertical两种

其中android:gravity用来设置控件的对齐方式,常用的属性值主要有:

属性值

说明

属性值

说明

top

不改变控件大小,对齐到容器顶部

center_vertical

不改变控件大小,对齐到容器纵向中央

bottom

不改变控件大小,对齐到容器底部

fill_vertical

纵向拉伸,以填满容器

left

不改变控件大小,对齐到容器左侧

center_horizontal

不改变控件大小,对齐到容器横向中央

right

不改变控件大小,对齐到容器右侧

fill_horizontal

横向拉伸,以填满容器

center

不改变控件大小,对齐到容器中央

fill

纵向横向同时拉伸,以填满容器

当需要为gravity设置多个值时,使用“|”分隔。
android:orientation和android:gravity属性在代码中可以分别使用setOrientation()和setGravity()方法设置。 而其中layout_width或layout_height则有三种常用属性:

设置

说明

"wrap_content"

View维度只会包含其中的对象

"fill_parent"

View维度会完全填满上层View的坐标维度

"match_parent"

和包含它的上层View有相同的设置

示例:
android:layout_width="match_parent"
android:layout_height="fill_parent"
使用text属性设置View显示的文字内容,示例:android:text="Button1"
使用gravity属性可以设置显示文字的位置,属性值有top、bottom、left、right、center_vertical、fill_vertical、center_horizontal、fill_horizontal、center、fill、clip_vertical、clip_horizontal,可以组合使用,示例:
android:gravity="top|left"
可以使用权重属性layout_weight来分配空间,设置控件在水平方向宽度或垂直方向高度的比例,用比例方式指定控件的相对大小。示例:
android:layout_weight="1"

线性布局示例:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="vertical">
  <TextView android:id="@+id/txt"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="时间:" />
  <Button android:id="@+id/btn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="开始计时" />
</LinearLayout>

2)相对布局RelativeLayout:

RelativeLayout布局是一种根据相对位置排列元素的方式,允许子元素指定相对于其他元素或父元素的位置。使用RelativeLayout可以任意放置控件位置,通过指定组件之间的关系,可让多个组件重叠在一起。所有Relative的组件默认对齐父节点的左上角。
与父控件相对位置的属性如下,这些属性值只取false或true:

android:layout_alignParentBottom

当前控件底端是否与父控件的底端对齐

android:layout_alignParentLeft

当前控件左侧是否与父控件的左侧对齐

android:layout_alignParentRight

当前控件右侧是否与父控件的右侧对齐

android:layout_alignParentTop

当前控件顶端是否与父控件的顶端对齐

android:layout_alignWithParentIfMissing

参照控件不存在或不可见时是否参照父控件

android:layout_centerHorizontal

当前控件是否位于父控件的横向中间位置

android:layout_centerVertical

当前控件是否位于父控件的纵向中间位置

android:layout_centerInParent

当前控件是否位于父控件的中央位置

与另一个控件相对位置有关的属性如下,属性值为其他控件的id:

android:layout_above

使当前控件位于给出id控件的上方

android:layout_below

使当前控件位于给出id控件的下方

android:layout_toLeftOf

使当前控件位于给出id控件的左侧

android:layout_toRightOf

使当前控件位于给出id控件的右侧

android:layout_alignBottom

使当前控件的下边界与给出id控件的下边界对齐

android:layout_alignLeft

使当前控件的左边界与给出id控件的左边界对齐

android:layout_alignTop

使当前控件的上边界与给出id控件的上边界对齐

android:layout_alignRight

使当前控件的右边界与给出id控件的右边界对齐

还有一些属性值以像素为单位的属性:

android:layout_marginLeft

当前控件距左侧的距离

android:layout_marginRignt

当前控件距右侧的距离

android:layout_marginTop

当前控件距上方的距离

android:layout_marginBottom

当前控件距下方的距离

示例:
android:layout_alignParentLeft="true"
android:layout_below="@id/textView1"
而设定相对位置可以使用marginLeft、marginRight、marginTop、marginBottom等属性:
android:layout_marginLeft="18dp"
相对布局示例:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent" android:layout_height="match_parent">
  <Button android:id="@+id/btn1" android:text="按钮1" android:textSize="20dp"
    android:layout_width="wrap_content" android:layout_height="wrap_content" />
  <Button android:id="@+id/btn2" android:text="按钮2" android:textSize="20dp"
    android:layout_width="wrap_content" android:layout_height="wrap_content"
    android:layout_toRightOf="id/button1" android:layout_below="@id/button1" />
  <Button android:id="@+id/btn3" android:text="按钮3" android:textSize="20dp"
    android:layout_width="wrap_content" android:layout_height="wrap_content"
    android:layout_toLeftOf="id/button2" android:layout_below="@id/button2" />
  <Button android:id="@+id/btn4" android:text="按钮4" android:textSize="20dp"
    android:layout_width="wrap_content" android:layout_height="wrap_content"
    android:layout_toRightOf="id/button2" android:layout_above="@id/button2" />
  <Button android:id="@+id/btn5" android:text="按钮5" android:textSize="20dp"
    android:layout_width="wrap_content" android:layout_height="wrap_content"
    android:layout_toRightOf="id/button2" android:layout_below="@id/button2" />
</RelativeLayout>

3)绝对布局AbsoluteLayout:

AbsoluteLayout是通过X、Y坐标来精确定位组件的一种布局方式,不需要指定参照物,而是使用整个手机界面作为坐标系。布局中的子控件的位置和布局都是通过坐标来指定的,android:layout_x和android:layout_y属性分别用于设置子控件的X坐标和Y坐标。
绝对布局示例:
<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent" android:layout_height="match_parent">
  <Button android:id="@+id/btn1" android:text="按钮" android:textSize="20dp"
    android:layout_width="wrap_content" android:layout_height="wrap_content"
    android:layout_x="40dp" android:layout_y="80dp"/>
</AbsoluteLayout>

4)框架布局FrameLayout:

该布局将所有子元素以层叠方式显示,后加的元素会被放在最顶层,覆盖之前的元素,适当设定时能管理复杂的视觉组件层级。要实现这种Fragment组件,必须要实现一个Fragment的子类,每一个Fragment都有自己的生命周期。要实现一个Fragment,至少需要实现onCreate、onCreateView、onPause函数。Fragment还有一些子类,弹出式对话框DialogFragment、显示表格数据ListFragment、显示用户首选PreferenceFragment。 FrameLayout特有的属性及方法有:

属性

方法

说明

android:foreground

setForeGround(Grawable)

设置绘制在子控件上的内容

android:foregroundGravity

setForeGroundGravity(int)

设置绘制在所有子控件之上内容的gravity属性

示例:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent" android:layout="match_parent">
  <TextView android:id="@+id/textview1" android:layout_gravity="center"
    android:layout_width="300dp" android:layout_height="300dp"/>
  <TextView android:id="@+id/textview2" android:layout_gravity="center"
    android:layout_width="240dp" android:layout_height="240dp"/>
  <TextView android:id="@+id/textview3" android:layout_gravity="center"
    android:layout_width="180dp" android:layout_height="180dp"/>
  <TextView android:id="@+id/textview4" android:layout_gravity="center"
    android:layout_width="120dp" android:layout_height="120dp"/>
  <TextView android:id="@+id/textview5" android:layout_gravity="center"
    android:layout_width="60dp" android:layout_height="60dp"/>
</FrameLayout>

5)表格布局TableLayout:

按照表格的顺序排列元素,用表格的行和列来定义布局,元素之间并没有实际的表格分界线。对于表格中列的定义常用的设置值有:

android:collapseColumns

指定哪些列要隐藏

android:shrinkColumns

指定哪些列要限缩

android:stretchColumns

指定哪些列要延伸

而对于单元格则有:

android:layout_span

指定该单元格会扩展几格

android:layout_column

指定该单元格从第几列开始排列

可以使用android:stretchColumns="0,1,2,3"指定Table的第1~4列都会延伸。
<TextView android:layout_column="1" android:text="cell5" />中layout_column="1"说明这个元素会从第2列开始排列,会从第1行的第2列开始对齐。
<TextView android:layout_span="2" android:text="cell8" />中layout_span="2"代表这个单元格会延伸两行,使下一个元素排在第3列。
表格布局示例:
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent" android:layout_height="match_parent">
  <TableRow>
    <Button android:id="@+id/btn1" android:text="按钮1" android:textSize="20dp"
      android:layout_width="wrap_content" android:layout_height="wrap_content" />
    <Button android:id="@+id/btn2" android:text="按钮2" android:textSize="20dp"
      android:layout_width="wrap_content" android:layout_height="wrap_content" />
  </TableRow>
  <TableRow>
    <Button android:id="@+id/btn3" android:text="按钮3" android:textSize="20dp"
      android:layout_width="wrap_content" android:layout_height="wrap_content" />
    <Button android:id="@+id/btn4" android:text="按钮4" android:textSize="20dp"
      android:layout_width="wrap_content" android:layout_height="wrap_content" />
  </TableView>
</TableLayout>

6)网格布局GridLayout:

该布局能够同时对X、Y轴的控件进行对齐,简化了对复杂布局的处理,提升了性能。布局中需要设定行与列的数值,还需要设定排列方向,常用设置有:

android:columnCount

设定最大列数

android:rowCount

设置最大行数

android:orientation

设置子元素布局方向

子元素属性可以指明所在的行与列,也可以不指明而按顺序排列:

android:layout_column

所在的列

android:layout_row

所在的行

子元素属性设置中如果需要跨行或列,则需要使用:

android:layout_columnSpan

占用的列数

android:layout_rowSpan

占用的行数

6.视图组件View:

View是用户界面的基础元素,通过View对象,可实现对布局、绘图、焦点变换、滚动条、屏幕区域的按键等功能。View常见的子类有:

类名

功能

事件监听器

TextView

文本视图

OnKeyListener

EditText

编辑文本框

OnEditorActionListener

Button

按钮

OnClickListener

Checkbox

复选框

OnCheckedChangeListener

RadioGroup

单选按钮组

OnCheckedChangeListener

Spinner

下拉列表

OnItemSelectedListener

AutoCompleteTextView

自动完成文本框

OnKeyListener

DataPicker

日期选择器

OnDateChangeListener

TimePicker

时间选择器

OnTimeChangeListener

DigitalClock

数字时钟

OnKeyListener

AnalogClock

模拟时钟

OnKeyListener

ProgressBar

进度条

OnProgressBarChangeListener

RatingBar

评分条

OnRatingBarChangeListener

SeekBar

搜索条

OnSeekBarChangeListener

GridView

网格视图

OnKeyDown,OnKeyUp

ListView

列表视图

OnKeyDown,OnKeyUp

ScrollView

滚动视图

OnKeyDown,OnKeyUp

View类有一个ViewGroup子类,通常作为其他组件的容器。ViewGroup类提供了一些方法:

方法

说明

void addView(View child)

用于添加子视图,将该View添加到当前视图组中

removeView(View view)

将指定的View从视图中移除

updateViewLayout(View v,
ViewGroup.LayoutParams params)

用于更新某个View布局

void bringChildToFront(View child)

将参数所指定的视图移动到所有视图之前显示

boolean clearChildFocus(View child)

清除参数所指定的视图的焦点

boolean dispatchKeyEvent(KeyEvent event)

将参数所指定的键盘事件分发给当前焦点路径的视图

boolean dispatchPopulateAccessibilityEvent
(AccessibilityEvent event)

将参数所指定的事件分发给当前焦点路径的视图

boolean dispatchSetSelected(boolean selected)

为所有的子视图调用setSelected()方法

7.对话框:

对话框是程序运行中的弹出窗口,Android系统提供了4种对话框:

对话框

说明

AlertDialog

提示对话框

ProgressDialog

进度对话框

DatePickerDialog

日期选择对话框

TimePickerDialog

时间选择对话框

用户还可以继承android.app.Dialog类自定义对话框。

1)AlertDialog:
创建普通对话框通过AlertDialog类生成,常用的方法有:

方法

描述

setTitle()

设置对话框title

setIcon()

设置对话框图标

setMessage()

设置对话框提示信息

setButton()

为对话框添加按钮

旧版本中普通对话框作为Activity的一部分被创建,通过调用onCreateDialog()方法来完成对话框的创建,显示对话框则使用showDialog()方法;新版本的对话框使用DialogFragment类来实现。AlertDialog中还可以使用列表、单选按钮或复选框。
⑴列表对话框:
列表对话框需要使用AlertDialog.Builder类,常用的方法有:

方法

描述

setTitle()

设置对话框title

setIcon()

设置对话框图标

setMessage()

设置对话框提示信息

setItems()

设置对话框要显示的list,一般用于显示多个命令

setSingleChoiceItems()

设置对话框显示一个单选list

setMultiChoiceItems()

设置对话框显示一个多选list

setPositiveButton()

为对话框添加确定按钮

setNegativeButton()

为对话框添加取消按钮

setNeutralButton()

为对话框添加中立按钮

⑵单选按钮对话框:
单选按钮对话框是指对话框的提示信息中包含单选按钮,该对话框也是使用DialogFragment来实现。
⑶复选框对话框:
复选框对话框是指对话框的提示信息中包含复选框,该对话框也是使用DialogFragment来实现。

2)进度对话框ProgressDialog:
进度对话框通过android.app.ProgressDialog类实现,该类是AlertDialog的子类。进度对话框有两种显示风格,分别是水平进度对话框和圆形进度对话框。进度对话框常用的方法有:

方法

描述

setMax()

确定(indeterminate=false)的进度条对话框里进度最大值的设置

setProgress()

当前进度值的设置

setSecondaryProgress()

第2个进度值的设置

incrementProgressBy()

当前进度值的增减

incrementSecondaryProgressBy()

第2进度值的增减

setProgressStyle()

进度对话框的风格,STYLE_SPINNER或STYLE_HORIZONTAL

3)日期及时间选择对话框DatePickerDialog和TimePickerDialog:
实现日期及时间选择对话框需要分别使用DatePickerDialog和TimePickerDialog类。

8.Toast消息提示:

Toast向用户提供快速的限时消息提示,当Toast被显示时无法获取焦点,不影响其他程序的使用,到时限后自动消失。
Toast对象的创建是通过Toast类的静态方法makeText()来实现的,有两种重载方法,分别接收字符串或字符串资源标识符为参数;Toast创建后,可以调用show()方法显示在屏幕上。在屏幕上显示的位置可以使用setGravity()方法设置。
一般来说,Toast只显示比较简短的文本消息提示,但也可以显示图片或使用自定义的界面,一般要使用addView()或setView()方法。

9.事件处理:

用户界面都是以事件驱动实现人机交互的,Android系统的UI控件事件包括键盘事件和触摸事件两大类,键盘事件包括按下、弹起等,触摸事件包括按下、弹起、滑动、双击等。Android系统的事件处理机制包括回调机制和监听接口两类。
Android基于回调机制的事件处理,主要做法是重写Android控件特定的回调方法,或者重写Activity的方法。Android中,每个View都有处理事件的回调方法,当某个事件没有没有被任何一个View处理时便会调用Activity中相应的回调方法。Android提供了以下方法供用户使用:

boolean onKeyDown(int keyCode,KeyEvent event)

当用户按下某个按键时触发该方法

boolean onKeyLongPress(int keyCode,KeyEvent event)

当用户长时间按住某按键时触发该方法

boolean onKeyShortcut(int keyCode,KeyEvent event)

当用户按下键盘上快捷键时触发该方法

boolean onKeyUp(int keyCode,KeyEvent event)

当用户松开某个按键时触发该方法

boolean onTouchEvent(MotionEvent event)

当用户触发触摸屏事件时触发该方法

boolean onTrackballEvent(MotionEvent event)

当用户触发轨迹球事件时触发该方法

几乎所有基于回调的事件处理方法都有一个boolean类型的返回值,该值用于标识该方法是否能完全处理该事件。如果回调方法返回true,表明该处理方法已完全处理该事件,该事件不会传播出去;如果回调方法返回false,表明该方法并未完全处理该事件,该事件会传播出去。
基于监听接口的事件处理是面向对象的,涉及三个对象:
·事件源EventSource:即事件发生的场所,通常指的是事件所发生的控件。
·事件Event:事件封装了界面控件上发生的特定事情,通常是一次用户操作,事件相关信息通过Event对象来获取。
·事件监听器EventListener:负责监听事件源所发生的事件,并对各种事件做出相应处理。
将事件源与事件监听器联系到一起,就需要为事件源注册监听,当事件发生时,系统才会自动处理。基于监听的事件处理,首先要获取界面控件(事件源),也就是被监听的对象,之后实现事件监听类,即必须实现其对应的Listener接口,然后为该控件添加监听。
程序中实现事件监听器通常有几种方式:
⑴Activity本身作为事件监听器:需要实现该接口中对应的事件处理方法。示例代码:
public class EventBtnActivity extends AppCompatActivity implements OnClickListener{
 @Override
 protected void onCreate(Bundle savedInstanceState){
  super.onCreate(savedInstanceState);
  ......
  btn.setOnClickListener(this);
 }
 @Override
 public void onClick(View v){
  ......
 }
}
⑵匿名内部类形式:
大部分情况下,事件监听器只是临时使用一次,所以使用匿名内部类形式的事件监听器更适合。代码示例:
public class EventBtnActivity extends AppCompatActivity{
 @Override
 protected void onCreate(Bundle savedInstanceState){
  super.onCreate(savedInstanceState);
  ......
  btn.setOnClickListener(new OnClickListener(){
   @Override
   public void onClick(View v){
    ......
   }
  });
 }
}
⑶内部类和外部类形式:
将事件监听器定义为当前类的内部类。示例代码:
public class MainActivity extends AppCompatActivity {
 @Override
 protected void onCreate(Bundle savedInstanceState){
  super.onCreate(savedInstanceState);
  ......
  btn.setOnClickListener(new MyClickListener());
 }
 class MyClickListener implements OnClickListener{
  @Override
  public void onClick(View v){
   ......
  }
 }
}
需要在内部类中实现该接口的事件处理方法,并在当前类中实例化这个内部类。也可以使用外部类实现该接口的事件处理方法,定义与使用方法与内部类相似,但比较少见。
⑷绑定XML控件标记:
Android中还有更简单地绑定事件的方式,即在布局文件中直接指定该控件的事件处理方法。对于大多数Android界面的组件,基本都支持onClick事件属性。示例:
<Button android:id="@+id/btn"
 android:layout_width="wrap_content" android:layout_height="wrap_content"
 android:onClick="clickMe" android:text="确认"/>
布局中的按钮Button绑定了一个事件处理方法clickMe,还需要在Activity中定义一个clickMe方法,示例代码:
public class EventBtnActivity extends AppCompatActivity{
 @Override
 protected void onCreate(Bundle savedInstanceState){
  super.onCreate(savedInstanceState);
  ......
 }
 public void clickMe(View v){
  ......
 }
}

1)处理键盘事件:
对于一个标准的Android设备,包含了多个能够触发事件的物理按键,各个可用的物理按键能够触发的事件有:

物理按键

KeyEvent

说明

电源键

KEYCODE_POWER

启动或唤醒设备,将界面切换到锁定的屏幕

后退键

KEYCODE_BACK

返回前一个界面

菜单键

KEYCODE_MENU

显示当前应用的可用界面

Home键

KEYCODE_HOME

返回到Home界面

查找键

KEYCODE_SEARCH

在当前应用中启动搜索

相机键

KEYCODE_CAMERA

启动相机

音量键

KEYCODE_VOLUMN_UP
KEYCODE_VOLUME_DOWN

控制当前上下文音量,如音乐播放器、手机铃声、通话音量等

方向键

KEYCODE_DPAD_CENTER
KEYCODE_DPAD_UP
KEYCODE_DPAD_DOWN
KEYCODE_DPAD_LEFT
KEYCODE_DPAD_RIGHT

某些设备中包含方向键,用于移动光标等

键盘键

KEYCODE_0,...,KEYCODE_9
KEYCODE_A,...,KEYCODE_Z

数字0~9,字母A~Z等按键

不过新版本中方向键、相机键等按键取消,改为屏幕触摸的软键盘,一些常用按键值为:

KEYCODE_POWER

电源键

KEYCODE_CALL

拨号键

KEYCODE_BACK

返回键

KEYCODE_ENDCALL

挂机键

KEYCODE_MENU

菜单键

KEYCODE_MUTE

话筒静音键

KEYCODE_HOME

Home键

KEYCODE_VOLUME_MUTE

扬声器静音键

KEYCODE_SEARCH

搜索键

KEYCODE_VOLUME_UP

音量增加键

KEYCODE_CAMERA

拍照键

KEYCODE_VOLUME_DOWN

音量减小键

KEYCODE_FOCUS

拍照对焦键

KEYCODE_NOTIFICATION

通知键

⑴基于回调机制的按键事件处理:
重写的onKeyDown()和onKeyUp()方法代码示例为:
public boolean onKeyDown(int keyCode,KeyEvent event){
 switch(keyCode){
  case KeyEvent.KEYCODE_0:
   showText("按下了数字键0");
   break;
  case KeyEvent.KEYCODE_BACK:
   showText("按下了后退键");
   break;
  ......
 }
 return super.onKeyDown(keyCode,event);
}
public boolean onKeyUp(int keyCode,KeyEvent event){
 switch(keyCode){
  case KeyEvent.KEYCODE_0:
   showText("按下了数字键0");
   break;
  case KeyEvent.KEYCODE_BACK:
   showText("按下了后退键");
   break;
  ......
 }
 return super.onKeyUp(keyCode,event);
}
⑵基于监听接口的按键事件处理:
为多个图片按钮设置监听器示例:
private ImageButton[] imageButtons=null;
imageButtons=new ImageButton[4];
imageButtons[0]=(ImageButton)findViewById(R.id.buttonA);
imageButtons[1]=(ImageButton)findViewById(R.id.buttonB);
imageButtons[2]=(ImageButton)findViewById(R.id.buttonC);
imageButtons[3]=(ImageButton)findViewById(R.id.buttonD);
for(ImageButton imageButton:imageButtons){
 imageButton.setOnKeyListener(MainActivity.this);
}
重写onKey()方法的代码示例:
public boolean onKey(View arg0,int arg1,KeyEvent arg2){
 switch(arg1){
  case 29:
   textview.setText("选择了按钮A");
   break;
  ......
  default:
   textview.setText("输入为其他按键");
   break;
 }
 return false;
}
Android系统中,键盘A的按键码为29,B的按键码为30,依次类推,Z的按键码为54。

2)处理触摸事件:
现在大多数手机都取消了外置键盘,而是通过触摸来操作。
⑴基于回调机制的触摸事件处理:
手机屏幕事件的处理方法是onTouchEvent,该方法在View类中定义,并且所有的View子类全部重写了该方法,应用程序可以通过该方法处理手机屏幕的触摸方法:
public boolean onTouchEvent(MotionEvent event)
参数event为手机屏幕触摸事件封装类,其中封装了该事件的所有信息,如触摸的位置、触摸的类型、触摸的时间等,该对象会在用户触摸手机屏幕时被创建。
onTouchEvent()方法的返回值也为boolean类型,当完整地处理了该事件且不希望其他回调函数再次处理时返回true,否则返回false。一般情况下,onTouchEvent()处理三种情况的事件,三种情况中的动作值不同:
·屏幕被按下:当屏幕被按下,会调用该方法来处理事件,此时MotionEvent.getAction()的值为MotionEvent.ACTION_DOWN。
·离开屏幕:当手指离开屏幕时也触发onTouchEvent()事件,此时MotionEvent.getAction()的值为MotionEvent.ACTION_UP。
·在屏幕拖动:该方法还负责处理手指在屏幕上滑动的事件,此时MotionEvent.getAction()的值为MotionEvent.ACTION_MOVE。
示例代码:
public boolean onTouchEvent(MotionEvent event){
 switch(event.getAction()){
  case MotionEvent.ACTION_DOWN:
   showToast("触摸屏幕");
   break;
  case MotionEvent.ACTION_UP:
   showToast("离开屏幕");
   break;
  case MotionEvent.ACTION_MOVE:
   showToast("在屏幕中拖动");
   break;
 }
 return super.onTouchEvent(event);
}
当手指在屏幕移动时,ACTION_MOVE事件会被系统一直响应。
⑵基于监听接口的触摸事件处理:
监听接口一般是使用setOnClickListener和setOnLongClickListener事件,代码示例:
button.setOnClickListener(new OnClickListener()){
 public void onClick(View v){
  text.setText("单击按钮");
 }
}
button.setOnLongClickListener(new OnLongClickListener()){
 public boolean onLongClick(View v){
  text.setText("长时间单击按钮");
  return false;
 }
}

3)处理焦点事件:
onFocusChanged()是焦点改变的回调方法,在某个控件重写了该方法后,当焦点发生变化时,会自动调用该方法来处理焦点改变事件。onFocusChanged()只能在View中重写。
void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect)
其中,参数gainFocus表示触发该事件的View是否获得焦点,当控件获得焦点时gainFocus为true,否则为false;参数direction表示焦点移动的方向,使用数值表示;参数previously FocusedRect表示在触发事件的View的坐标系前一个获得焦点的矩形区域,表示焦点从哪里来,如果不可用则为null。
使用onFocusChanged()时,会使用到与焦点有关的方法:

setFocusable()

用于设置View是否可以拥有焦点

isFocusable()

用于判断View是否可以拥有焦点

setNextFocusDownId()

用于设置View的焦点向下移动后获得焦点View的Id

hasFocus()

用于判断View的父控件是否获得了焦点

requestFocus()

用于尝试让此View获得焦点

isFocusableTouchMode()

用于设置View是否可以在触摸模式下获得焦点,默认情况下不可用

4)手势的创建与识别:
目前大多数手机都支持手写输入,Android系统可以根据用户输入的内容,在预定义的词库中查找最佳匹配项供用户选择。
⑴手势创建:在Android模拟器中有Gestures Builder应用,打开后单击Add gesture按钮,可以增加手势,添加完成后单击Done按钮保存。继续添加多个手势。
⑵手势导出:在手势创建完成后需要将保存手势的文件导出,以便在应用程序中使用。在DDMS视图中,File Explorer中找到\mnt\sdcard\gestures文件,使用右上角的导出按钮将文件导出。
⑶手势识别:要使用手势识别,需要在XML布局文件中配置android.gesture.GedtureOverlay View控件,这是一个透明覆盖层,看覆盖在其他控件上方,也可以包含其他控件。
GedtureOverlayView控件包含的属性有:

android:eventsInterceptionEnabled

定义当手势被识别出来时,是否拦截手势动作

android:fadeDuration

当用户画完手势时,手势淡出效果的持续时间,单位ms

android:fadeEnabled

定义识别完手势后,手势是否自动淡出

android:fadeOffset

淡出延迟,单位ms,即用户画完手势后到淡出间的时间

android:gestureColor

描绘手势的颜色

android:gestureStrokeAngleThreshold

识别是否为手势前,一笔必须包含的最小曲线度

android:gestureStrokeLengthThreshold

识别是否为手势前,一笔的最小长度

android:gestureStrokeSquarenessThreshold

识别是否为手势前,一笔的偏斜度阈值

android:gestureStrokeType

定义手势的类型,表示是否一笔画成,multiple为多笔画

android:gestureStrokeWidth

画手势时,画笔的宽度

android:orientation

指出是水平(vertical)或垂直(horizontal)笔画自动定义手势

android:uncertainGestureColor

未确定为手势前,描绘用户笔画的颜色

手势处理需要使Activity实现OnGesturePerformedListener,声明GestureLibrary对象,并加载手势文件,示例代码:
private GestureLibrary library=null;
......
library=GestureLibraries.fromRawResource(this,R.raw.gestures);
if(!library.load()){
 finish();
}
GestureOverlayView gesture=(GestureOverlayView)findViewById(R.id.gesture);
gesture.addOnGesturePerformedListener(this);
⑷重写onGesturePerformed()方法,在该方法中获取得分最高的预测结果并显示,示例:
public void onGesturePerformed(GestureOverlayView overlay,Gesture gesture){
 ArrayList<prediction> gesture=library.recognize(gesture);
 int index=0;
 double score=0;
 for(int i=0;i<gesture.size();i++){
  Prediction result=gestures.get(i);
  if(result.score>score){
   index=i;
   score=result.score;
  }
 }
 showToast(gesture.get(index).name);
}
代码中,recognize()方法获取全部预测结果,然后获取得分最高预测的索引号。

10.Android中的Java语言基础:

Android程序使用Java语言编程。Java是一种面向对象的编程语言,核心是类class。具有相同特性和行为的实体的抽象就是类,类实际上是一种数据类型,包含内部变量和函数,称为属性和操作方法。类class和对象Object的关系是抽象与具体的关系,class是Object的抽象,Object是class的一种实现,Object属于class。
1) 类的声明:
[<modidiers>] class <class_name> {
[<attribute_declarations>]
[<constructor_declarations>]
[<method_declarations>]
}
各组成部分的含义:
·<modidiers>:修饰符,包括public、private、protected、abstract、final等关键字
·class:关键字,表明是一个类的定义
·<class_name>:类的名称,一般首字母使用大写
·[<attribute_declarations>]:属性attribute声明部分
·<constructor_declarations>:构造方法constructor声明部分
·<method_declarations>:方法method声明部分
示例:
public class Student {
//定义属性
String name;
String sex;
int grade;
int age;
//
public void getName() {
name=_name;
}
public String getName() {
return name;
}
......
}

2)属性的声明:
类定义中所包含的数据称为属性。属性声明的语法为:
[<modidiers>] <data_type> <attr_name>
其中:
·<data_type>:是该属性的数据类型
·<attr_name>:属性名称,一般首字母使用小写
方法的声明:
方法表示类的操作,可以认为是类的函数。语法规则为:
[<modidiers>] <return_type> <method_name>([<argu_list>]) {
[<method body>]
}
其中:
·<return_type>:该方法的返回值类型
·<method_name>:方法名,通常首字母为小写
·[<argu_list>]:方法的参数列表,多个参数中间用逗号分隔
·[<method body>]:方法体,0到多行语句
3)构造方法:
构造方法是创建一个类的实例时需要调用的方法。构造方法的修饰符可以使用public、protected、private这类访问的修饰或没有修饰符,而不能使用abstract、final、native、static、synchronized这类非访问性质的修饰。构造器可以有任何类型的返回值,也可以没有返回值,没有返回值不需要使用void。构造方法的名字使用类名,因为类名首字母常用大写,所以构造方法首字母也常为大写。
Java中,每个类都必须至少有一个构造方法。如果没有定义构造方法,编译器会自动加上一个。

4)封装:
在程序上隐藏对象的属性和实现细节,仅对外公开接口,控制在程序中属性的读和修改的访问级别,这就是封装。封装在原则上要求将尽可能多的内容藏起来,而对外提供简捷的接口,使用者不必了解具体的实现细节,而只是通过外部接口来使用类的成员。
5)继承:
继承,是使用已存在的类为基础建立新类,建立的新类称为子类,而被继承的类则称为父类。继承使得子类具有父类的各种属性和方法,不需要再次编写相同的代码。子类继承父类时,也可以重新定义某些属性,并重写某些方法,即覆盖父类的原有属性和方法,使其获得与父类不同的功能,另外还可以追加新的属性和方法。但子类不能选择性地继承父类。
Java不支持多继承,即子类只能有一个父类,但可以实现多个接口,以克服单继承的缺点。
6)多态:
多态Polymorphism,在面向对象的编程语言中描述接口的多种不同实现方式,即同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。多态,意味着一个对象有着多重特征,可以在特定的情况下,表现不同的状态,从而对应着不同的属性和方法。
多态,是面向对象的程序设计语言的核心特征,支持多态是面向对象的语言,而不支持多态的被称为基于对象的语言,比如JavaScript。
7)抽象类:
用关键字abstract声明的方法被称为抽象方法,这种方法只有声明,而不含方法的具体实现。如果一个类中至少包含一个或多个以上的抽象方法,则这个方法所在的类必须声明为抽象类。
如果一个类中没有包含足够的信息来描绘一个具体对象就是抽象类,抽象类不能实例化成对象,只能继承,然后在子类中提供方法的具体实现。
8)接口:
Java接口本身没有任何实现,只描述public行为。接口的方法只能是抽象的和公开的,不能有构造器,接口的属性可以有public、static和final属性。
接口把方法的特征和方法的实现分开,包装了相关的操作和属性,需要使用implements来实现一个类。使用接口,弥补了Java类不能多继承的缺点,是一种变相的多继承实现。
9)集合框架:
集合框架是一种表示和操作集合的标准体系结构,包含对外的接口、接口的实现和对集合运算的方法。Java有三类集合框架,List、Set和Map。
List、Set都实现了Collection接口,Collection提供了添加、删除、查询等基本操作,有isEmpty方法。List接口对Collection进行了简单扩充,可以将任何物体放到一个List容器中,并在需要时从中取出,具体实现的类有ArrayList和LinkedList。
ArrayList是一种用数组实现的List,以类似数组的形式存储,因此随机访问速度快,但往其中插入和删除元素时比较慢,因此能用于遍历的场合。
LinkedList的内部实现是链表,适合于在链表中频繁插入和删除操作场合,但随机访问的速度相对比较慢。因为LinkedList有addFirst、addLast、getFirst、getLast、removeFirst、removeLast等方法,可以当成栈stack、队列queue、双向队列deque来使用。
Map是一种把键和值对象进行关联的容器,一个Map中的键不允许重复,即有唯一性。使用过程中,某个键所对应的值可能会发生变化。键与值的关联很简单,用put(key,value)方法可将一个键与一个值相关联,用get(key)可获得与此键对应的值。Map有HashMap和TreeMap两种,HashMap使用哈希表算法实现,方便快速查找一个键;而TreeMap则是用基于树的数据结构实现,对键按序存放,有firstKey、lastKey等方法,可用subMap获取树的一部分。
Java的集合框架中,对于参数值是未知类型的容器,只能读取其中的元素,不能向其中添加元素,因为类型未知,所以编译器无法识别添加元素的类型与容器的类型是否兼容,唯一的类外是null。如List<?> list;
10)泛型:
泛型Generics是对Java语言的类型系统的扩展,以支持创建可以按类型进行参数化的类,可以把类型参数看作指定类型的占位符。使用方法示例:
List<Integer> list=new ArrayList<Integer>();
list.put(new Integer(3));
Integer I=list(0);
泛型可以用于方法和类,即泛型方法和泛型类。类中的方法要支持多个数据类型需要对方法进行重载,使用泛型后,可以定义多个参数以及返回值之间的关系:
piblic <T> void write(<T>I,<T>[] array);
定义带类型参数的类时,紧跟内名之后的<>内,指定一个或多个类型参数的名字,同时也可以对类型参数的取值范围进行限定,多个类型参数之间用逗号分隔。定义了类型参数后,可以在定义位置之后的类的几乎任意地方(静态块、静态属性、静态方法除外),使用类型参数,就像使用普通类型一样。示例:
public class Text<T>{}
父类定义的类型参数不能被子类继承。

Copyright@dwenzhao.cn All Rights Reserved   备案号:粤ICP备15026949号
联系邮箱:dwenzhao@163.com  QQ:1608288659