Unit 4. Android 生命周期
Android 系统中的进程优先级由高到低
Android 组件
组件是可以调用的基本功能模块,Android 应用程序就是由组件组成的
Android 系 统 有 四 个 重 要 的 组 件 , 分 别 是 Activity 、 Service 、BroadcaseReceiver 和
ContentProvider
Activity 是 Android 程序的呈现层,显示可视化的用户界面,Android 应用程序可以包含
一个或多个 Activity,一般在程序启动后会呈现一个 Activity。
Service 用于没有用户界面,但需要长时间在后台运行的应用
BroadcaseReceiver 是用来接受并响应广播消息的组件
ContentProvider 是 Android 系统提供的一种标准的共享数据的机制,应用程序可以通过
ContentProvider 访问其他应用程序的私有数据,私有数据可以是存储在文件系统中的文件,
也可以是 SQLite 中的数据库
Activity 表现为四种状态,分别是活动状态、暂停状态、停止状态和非活动状态
Activity 事件的回调函数:
protected void onStart();
protected void onRestart();
protected void onResume();
protected void onPause();
protected void onStop();
protected void onDestroy();
Activity:
Android 系统提供了两种调试工具 LogCat 和 DevTools,用于定位、分析及修复程序中
出现的错误
LogCat 程序调试原理
1.引入 android.util.Log 包
2.使用 Log.v(),Log.d(),Log.i(),Log.w() 和 Log.e()五个函数在程序中设置“日志点”
3.当程序运行到“日志点”时,应用程序的日志信息便被发送到 LogCat 中
4.判断“日志点”信息与预期的内容是否一致
E.g.
final static String TAG = "LOGCAT"; Log.v(TAG,"Verbose");
DevTools 是用于调试和测试的工具,包括了一系列用户各种用途的小工具
Unit 5. Android 用户界面
常见的系统控件包括 TextView、EditText、Button、ImageButton、Checkbox、RadioButton、
Spinner、ListView 和 TabHost
TextView:显示字符串,EditText 是一个具有编辑功能的 TextView
相应的 XML 文件:
Test.java:
TextView txv=(TextView)findViewByID(R.id.TextView01);
txv.setText("User:");
ImageButton:
将 img1 拷贝到/res/drawable 文件夹下(R.java 中自动更新)
imageButton.setImageResource(R.drawable.img1);
按钮响应点击事件:添加点击事件的监听器
imageButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)点击事件的回调函数
{
txv.setText("ImageButton 按钮");
}
})
每个 View 仅可以注册一个点击事件的监听器,如果使用 setOnClickListener()函数注册
第二个点击事件的监听器,之前注册的监听器将被自动注销.
多个按钮注册到同一个点击事件的监听器上,代码如下:
Button.OnClickListener buttonListener = new Button.OnClickListener(){
@Override
public void onClick(View v) {
switch(v.getId()){
case R.id.Button01:
textView.setText("Button 按钮");
return;
case R.id.ImageButton01:
textView.setText("ImageButton 按钮");
return;
}
}};
button.setOnClickListener(buttonListener);
imageButton.setOnClickListener(buttonListener);
CheckBox 和 RadioButton:
怎样定义同组中的 RadioButton?
XML 中:
Test.java 中:
RadioButton radioButton1 =(RadioButton)findViewById(R.id.RadioButton01);
RadioButton.OnClickListener rblistener=new RadioButton.OnClickListener()
{
public void OnClick(View v)
{
//process;
}
};
radioButton1.setOnClickListener(rblistener);
Spinner:(similar to ComboBox)
Test.java:
Spinner spinner=(Spinner)findViewById(R.id.Spinner01);
Listlist=new ArrayList( );
list.add("item1");
list.add("item2");
ArrayAdapteradapter=new ArrayAdapter (
this,android.R.layout.simple_spinner_item, list );
//数组适配器能够将界面控件和底层数据绑定在一起
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
ListView:(垂直显示的列表控件)
ListView listv=(ListView)findViewById(R.id.ListView01);
Listlist=new ArrayList();
List.add("item1");
List.add("item2");
ArrayAdapter adapter=new ArrayAdapter
listv.setAdapter(adapter);
(this, android.R.layout.simple_list_item_1, list );
AdapterView.OnItemClickListener listvListener=new AdapterView.OnItemClickListener(){
public void onItemClick(AdapterView> arg0, View arg1, int arg2, long arg3) {
String msg =””;
textView.setText(msg);
}};
}
TabHost:实现多个分页之间的快速切换(Similar to TabControl)
有几个 tabpage 就建立几个 xml
Test.java:
public class TabDemo extends TabActivity {
//普通的都是 extends Activity
// 与以往继承 Activity 不同,TabActivity 支持内嵌多个 Activity 或 View
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TabHost tabHost = getTabHost(); //获得 Tab 标签页的容器
LayoutInflater.from(this).inflate(R.layout.tab1, tabHost.getTabContentView(),true);
//LayoutInflater 将 tab1.xml 文件中的布局转换为 Tab 标签页可以使用的 View 对象
LayoutInflater.from(this).inflate(R.layout.tab2,tabHost.getTabContentView(),true);
LayoutInflater.from(this).inflate(R.layout.tab3,tabHost.getTabContentView(),true);
tabHost.addTab(tabHost.newTabSpec("TAB1")
.setIndicator("线性布局").setContent(R.id.layout01));
//使用 addTab()函数在 tabHost 上添加了第 1 个标识为"TAB1"的分页
tabHost.addTab(tabHost.newTabSpec("TAB2")
.setIndicator("绝对布局").setContent(R.id.layout02));
tabHost.addTab(tabHost.newTabSpec("TAB3")
.setIndicator("相对布局").setContent(R.id.layout03));
}
界面布局:
声明 Android 程序的界面布局有两种方法:
使用 XML 文件描述界面布局
在程序运行时动态添加或修改界面布局
用户既可以独立使用任何一种声明界面布局的方式,也可以同时使用两种方式
使用 XML 文件声明界面布局的特点:
将程序的表现层和控制层分离
在后期修改用户界面时,无需更改程序的源代码
可视化界面加快设计
线性布局 LinearLayout:
如果垂直排列,则每行仅包含一个界面元素
如果水平排列,则每列仅包含一个界面元素
框架布局 FrameLayout
表格布局 TableLayout:
添加行为 TableRow
相对布局(RelativeLayout):
e.g.
android:layout_below="@id/label"
android:layout_alignParentRight="true"
android:layout_toLeftOf="@id/cancel"
android:layout_alignTop="@id/cancel"//声明与 ID 为 cancel 的元素在相同的水平位置
绝对布局(AbsoluteLayout)
android:layout_x="40dip"
android:layout_y="40dip"
菜单:
Android 系统支持三种菜单:
选项菜单(Option Menu)
子菜单(Submenu)
快捷菜单(Context Menu)
选项菜单
分为图标菜单(Icon Menu)& 扩展菜单(Expanded Menu)。
图标菜单能同时显示文字和图标的菜单,最多支持 6 个子项,但不支持单选框和复选框
扩展菜单是在图标菜单子项多余 6 个时才出现,是垂直的列表型仅有文字菜单
重载 Activity 的 onCreateOptionMenu()函数,才能在 Android 应用程序中使用选项菜单
public boolean onCreateOptionsMenu(Menu menu){
menu.add(0,MENU_DOWNLOAD,0,"下载设置");//MENU_DOWNLOAD=1
//MenuItem android.view.Menu.add(int groupId, int itemId, int order, CharSequence title)
menu.add(0,MENU_DOWNLOAD,0,"下载设置").setIcon(R.drawable.download);
.setShortcut(’,’d’);//快捷键
return true;
}
重载 onPrepareOptionsMenu()函数,能够动态的添加、删除菜单子项,或修改菜单的
标题、图标和可见性等内容
E.g.
下面的代码是在用户每次打开选项菜单时,在菜单子项中显示用户打开该子项的次数
public boolean onPrepareOptionsMenu(Menu menu){
MenuItem uploadItem = menu.findItem(MENU_UPLOAD);
uploadItem.setTitle("上传设置:" +String.valueOf(MenuUploadCounter));
return true;
}
onOptionsItemSelected ()函数能够处理菜单选择事件,且该函数在每次点击菜单子项时
都会被调用
public boolean onOptionsItemSelected(MenuItem item){
switch(item.getItemId()){//获取到被选择菜单子项的 ID
case MENU_DOWNLOAD:
MenuDownlaodCounter++;
return true;
case MENU_UPLOAD:
MenuUploadCounter++;
return true;
}
return false;
}
子菜单
子菜单不支持嵌套,添加是使用 addSubMenu()函数实现
SubMenu uploadMenu = (SubMenu) menu.addSubMenu(0,MENU_UPLOAD,1,"上传设置")
.setIcon(R.drawable.upload);
uploadMenu.setHeaderIcon(R.drawable.upload);
uploadMenu.setHeaderTitle("上传参数设置");
uploadMenu.add(0,SUB_MENU_UPLOAD_A,0,"上传参数 A");
uploadMenu.add(0,SUB_MENU_UPLOAD_B,0,"上传参数 B");
快捷菜单
选项菜单中的 onCreateOptionsMenu()函数仅在选项菜单第一次启动时被调用一次
快捷菜单的 onCreateContextMenu()函数每次启动时都会被调用一次
菜单选择事件的处理需要重载 onContextItemSelected()函数,该函数在用户选择快捷菜
单中的菜单子项后被调用,与 onOptionsItemSelected ()函数的使用方法基本相同
菜单在 XML 中的实现:
界面事件
按键事件将传递给 onKey()函数进行处理
触摸事件将传递给 onTouch()函数进行处理
是否继续传递事件给其他处理函数是由事件监听器处理函数的返回值决定的,取决于监
听处理函数返回值。
按键事件:
entryText.setOnKeyListener(new OnKeyListener(){
@Override
public boolean onKey(View view, int keyCode, KeyEvent keyEvent) {
int metaState = keyEvent.getMetaState();
int unicodeChar = keyEvent.getUnicodeChar();
String msg = "";
msg +="按键动作:" + String.valueOf(keyEvent.getAction())+"\n";
msg +="按键代码:" + String.valueOf(keyCode)+"\n";
msg +="按键字符:" + (char)unicodeChar+"\n";
msg +="UNICODE:" + String.valueOf(unicodeChar)+"\n";
msg +="重复次数:" + String.valueOf(keyEvent.getRepeatCount())+"\n";
msg +="功能键状态:" + String.valueOf(metaState)+"\n";
msg +="硬件编码:" + String.valueOf(keyEvent.getScanCode())+"\n";
msg +="按键标志:" + String.valueOf(keyEvent.getFlags())+"\n";
labelView.setText(msg);
if (checkBox.isChecked())
return true;
return false;
else
}
触摸事件:
重载 onTouch ()函数
touchView.setOnTouchListener(new View.OnTouchListener(){
@Override
public boolean onTouch(View v, MotionEvent event) {
//过程代码……
return true/false;
})
TextView touchView = (TextView)findViewById(R.id.touch_area);
touchView.setOnTouchListener(new View.OnTouchListener(){
@Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action) {
case (MotionEvent.ACTION_DOWN):