8.1.1.概述
除了在Java代码中定义数组,Android还提供了在资源中定义数组,然后在Java代码中解析资源,从而获取数组的方法。
实际开发中,推荐将数据存放在资源文件中,以实现程序的逻辑代码与数据分离,便于项目的管理,尽量减少对Java代码的修改。
8.1.2.在资源中定义数组
步骤1、在res/values文件夹下创建arrays.xml文件;
步骤2、在arrays.xml文件中创建一个数组,如下代码所示:
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string-array name="citys">
<item>北京</item>
<item>天津</item>
<item>上海</item>
<item>重庆</item>
</string-array>
</resources>
说明:
Android规定存放数组的文件必须在res/values文件夹下创建,推荐存放资源数组的文件名为arrays.xml。
以上定义了一个含有四个直辖市名称的字符串数组,数组名是citys,数组元素在<item>标签中存放。
8.1.3.Resource类
8.1.3.1.概述
Android提供了Resource类,通过该类提供的方法可以很方便地获取资源中的数据,如资源中定义的数组。
8.1.3.2.创建Resources对象
getResource();
作用:该方法是ContextWrapper类的静态方法,用于创建Resources对象。
示例:以下代码创建一个Resources对象:
Resources res=Resources.getResource();
说明:该方法必须在Context类及其子类中才能使用。
8.1.3.4.常用方法
getStringArray(int resId);
作用:获取资源索引值为resId的字符串类型的数组。
示例:以下代码将8.1.2.中创建的citys数组获取并存放在数组citys中:
Resources res=getResources();
String[] citys=res.getStringArray(R.array.citys);
提示:Resources还提供了获取int、boolean等类型的数组的方法,本章仅介绍本章代码中用到的获取字符串数组的方法。
8.2.ListView控件
8.2.1.概述
ListView是android应用程序中使用频率最高的控件。该控件使用垂直列表的方式显示多个选项,特别适合于手机这种屏幕相对较小的设备。
ListView控件的特点:每个列表项独占一行,每行的布局都相同,数据和布局分离,
数据来自适配器,ListView只负责显示,图-1是ListView的一个应用:
图-1
8.2.2.常用属性
XML属性
说明
choiceMode
设置ListView的选择方式,有三个值:
(1)none:默认方式
(1) SingleChoice:单选
(2) multipleChoice:复选
divider
设置列表项的分隔条,分隔条可以是颜色值也可以是图片
entries
指定一个字符串数组资源,用于显示在ListView中
8.2.3.常用方法
1、Object getItemAtPosition(int position)
作用:获得当前列表项
参数-position:当前列表项的索引值。
示例:
//获取索引值是position的列表项,转换为字符串
String text=(String)listView.getItemAtPosition(position);
2、void setChoiceMode(int choiceMode)
作用:设置列表的选择方式
参数-choiceMode有以下三个可选值:
进程的优先级
12.1.1.概述
Android规定:进程的优先级分为以下五个级别,如图-1所示:
图-1
1、 前台进程 -Activte process
Active (前台) process是包含(与用户交互的)控件的那种应用程序。这些是Android通过回收资源来极力保护的进程。Active process包括:
(1)处于“active”状态的Activity,它们运行在前台来响应用户的事件。
(2)Activity Service或者正在执行onReceive事件处理函数的Broadcast Receiver。
(3)正在执行onStart,onCreate,OnDestroy事件处理函数的Service。
2、 可见进程-Visible Process
可见但不活动的进程是那些拥有“可见”Activity的进程。“可见”Activity是那些在屏幕上可见,但不是在前台或不响应用户事件的Activity。这种情况发生在当一个Activity被部分遮盖的时候(被一个非全屏或者透明的Activity)。可见进程只在极端的情况下,才会被杀死来保证Active Process的运行。包括以下情况:
(1)可见的Activity,但处于暂停(onPause()) 状态;
(2)被可见Activity绑定的Service
3、 服务进程 Service process
进程中包含已经启动的Service。Service以动态的方式持续运行但没有可见的界面。因为Service不直接和用户交互,它们拥有比visible Process较低的优先级。它们还是可以被认为是前台进程,不会被杀死,直到资源被active/visible Process需求。
4、 背景进程 Background process
进程中的Activity不可见和进程中没有任何启动的Service,这些进程都可以看作是后台进程。在系统中,拥有大量的后台进程,并且Android按照后看见先杀掉的原则来杀掉后台进程以获取资源给前台进程。
5、 空进程-Empty process
为了改善整个系统的性能,Android经常在内存中保留那些已经走完生命周期的应用程序。Android维护这些缓存来改善应用程序重新启动的时间。这些进程在资源需要的时候常常被杀掉。
当一个进程被杀掉,进程保留,变成空进程。
12.1.2.设置/取消Service为前台进程的方法
由上所述,Service排在进程的第三优先级,通常耗时的操作是放在线程中,那么将这样的线程放在Service中将会有较高的优先级,降低被Android系统杀掉的几率。
若是将线程放在Activity中,当Activity被完全遮盖,处于onStop状态时,其进程的优先级别降为第四级。明显不如放在处于第三级别的Service中更保险。
应用场景,如音乐播放器,通过在前台做其它操作时,音乐播放器在后台播放音乐,这种情况将播放音乐的线程放在Service中是适宜的。
Service类中有两个方法,分别用来设置Service为前台进程和取消前台进程。被设置为前台进程的Service拥有最高的优先级别,被Android系统杀掉的几率降至最低。
1、startForeground(int id,Notification noti);
作用:设置Service对象为前台进程。
说明:
第一个参数是通知的id值。
第二个参数是通知对象。
startForegroud方法的参数与通知管理器相同,使用上也类似,都是发送一个通知,并指定该通知对象的id值。
2、stopForeGround(int id);
作用:取消(指定id值所通知的Service对象)前台进程。
12.1.3.设置Service为前台进程的步骤
步骤1、在Service类的onStartCommand方法中(通常在该方法中)创建Intent对象,并指定与其绑定的Activity,示例代码如下:
Intent foreIntent=new Intent(this, MainActivity.class);
步骤2、创建PendingIntetn对象
PendingIntent pintent=PendingIntent.getActivity(
this, 0, foreIntent, PendingIntent.FLAG_UPDATE_CURRENT);
说明:第四个参数指明在通知栏随时刷新通知。
步骤3、创建通知对象,示例代码如下:
Notification noti=new Notification(
R.drawable.icon,"notification",System.currentTimeMillis());
说明:
第一个参数是通知栏中显示的本通知的图标。
第二个参数是通知栏中显示的本通知的标题。
第三个参数是本通知发出的时间。
步骤4、将此通知放到通知栏的(Ongoing)正在运行组中,示例代码如下:
noti.flags=Notification.FLAG_ONGOING_EVENT;
步骤5、设置通知的点击事件,示例代码如下:
noti.setLatestEventInfo(this, "title","content", pintent);
步骤6、向指定的Activity发送通知,并设置当前的Service对象为前台进程,示例代码如下:
startForeground(97789, noti);
12.1.4.示例
运行图-1所示的窗口:
图-2
1、单击图-1中的start foreground按钮,将启动一个Service对象,并设置改Service为前台进程,在该在日志窗口中出现图-2中红框内的第一行信息。
2、单击图-2中的stop foreground按钮,将取消Service的当前进程,并在日志窗口中显示图-2中红框内的第二行信息。
以下列出关键代码:
步骤1、创建项目exer12_01,包名为com.tarena.exer12_01,项目入口:MainActivity类,该中关键代码如下所示:
@Override
public void onClick(View v) {
//创建Intent对象,并设置目标组件为MyService
Intent intent=new Intent();
intent.setClass(this, MyService.class);
switch(v.getId()){
case R.id.btnStartFore:
//设置intent.action的值为Constant.ACTION_FORE
intent.setAction(Constant.ACTION_FORE);
startService(intent);//启动服务
break;
case R.id.btnStopFore:
//设置intent.action的值为Constant.ACTION_STOP_FORE
intent.setAction(Constant.ACTION_STOP_FORE);
startService(intent);
break;
case R.id.btnStopService:
stopService(intent);//停止服务
break;
}
}
步骤2、在src/com.tarena.exer12_01包下创建MyService.java该类继承自Service类。关键代码如下所示:
@Override