相应能力对于Android系统来说太重要了。为了确保APP快速地应对用户的交互和系统事件,我们需要将所有的耗时处理和I/O相关的操作移到子线程中去。
文件操作、网络查询、数据库事务、还有复杂的计算都应该在后台线程中进行。
Android提供了一系列的措施可以让你将处理移到后台。
比如:Thread+Handler的组合,AsyncTask。
AsyncTask用来执行短期的处理非常合适。但是呢,Activity重启的时候,它是不会有所保留的。比如说设备配置发生改变,导致Activity重启,然后AsyncTask就会被打断。
通常推荐,那种相对更长时间操作的,可以选择Service组件。
相似的,CursorLoader用来优化ContentProvider的查询非常合适。
创建新的AsyncTask
每个建立的AsyncTask都需要指定3个泛型参数类型,第一个:输入的参数,第二个:进度值,第三个:结果值。
下面直接看例子:
private class MyAsyncTask extends AsyncTask<String, Integer, String> {
@Override
protected String doInBackground(String... parameter) {
// Moved to a background thread.
String result =;
int myProgress = 0;
int inputLength = parameter[0].length();
// Perform background processing task, update myProgress]
for (int i = 1; i <= inputLength; i++) {
myProgress = i;
result = result + parameter[0].charAt(inputLength-i);
try {
Thread.sleep(100);
} catch (InterruptedException e) { }
publishProgress(myProgress);
}
// Return the value to be passed to onPostExecute
return result;
}
@Override
protected void onProgressUpdate(Integer... progress) {
// Synchronized to UI thread.
// Update progress bar, Notification, or other UI elements
asyncProgress.setProgress(progress[0]);
}
@Override
protected void onPostExecute(String result) {
// Synchronized to UI thread.
// Report results via UI update, Dialog, or notifications
asyncTextView.setText(result);
}
}
下面介绍这几个函数:
1.doInBackground 故名思议,这个方法会执行在后台线程。可以在这个方法内做耗时的操作。你可以使用publishProgress方法去传递参数值给onProgressUpdate方法。
2.onProgressUpdate 这个方法用来接收过度时期的进度值,(比如你可以使用这个方法更新ProgressBar的进度)。这个方法是与UI线程同步的。
3.onPostExecute 当doInBackground完成的时候,它的返回值会作为onPostExecute的结果参数传进来,然后你就可以以此来更新UI。同样这个方法也是与UI线程同步的。
运行一个AsynTask:
String input =redrum ... redrum ;
new MyAsyncTask().execute(input);
注意:execute 方法只能执行1次,再次调用会报错。
介绍Intent Service
Intent Service是一个非常好的包装类,实现了最好的方式让后台的Service执行一系列的任务集,比如循环的网络更新或者数据处理。
它把发过来的Intent放入它自己维护的队列中,然后一个个拿出来在后台线程中处理。当所有的Intent都被处理完的时候,Intent Service会自动结束自己。
主要的方法onHandleIntent是在后台线程的:
public class MyIntentService extends IntentService {
public MyIntentService(String name) {
super(name);
// TODO Complete any required constructor tasks.
}
@Override
public void onCreate() {
super.onCreate();
// TODO: Actions to perform when service is created.
}
@Override
protected void onHandleIntent(Intent intent) {
// This handler occurs on a background thread.
// TODO The time consuming task should be implemented here.
// Each Intent supplied to this IntentService will be
// processed consecutively here. When all incoming Intents
// have been processed the Service will terminate itself.
}
}
带过一下Loader
Loader是在Android 3.0(API 11)中引入的,在Android Support Library中也可用,比如以前用到的CursorLoader。
当你想创建自己的Loader的时候,通常你只需要继承 AsyncTaskLoader。
手动异步的时候,有个方法需要提下:
View的runOnUiThread。此方法运行在UI线程。
使用ALARMS
Alarms用来发射Intents,在确定的时间或者时间间隔。不像Timer,Alarms操作不受限于你的APP,所以你可以用来触发APP事件或者动作事件,即便APP已经被关了。
Alarms非常强大,你可以与广播混合使用,你能够用来发射Broadcast Intent,启动Service,或者甚至打开Activity,不需要你的APP被打开或者运行。
Alarms是一个有效的方式用来减少你的APP资源需求,比如使你能够停止服务,然后减少时间。
你可以用Alarms来计划基于网络查询进行规律的更新,去安排耗时的操作在不紧张的时间,或者安排操作失败后的再次尝试。
当设备在睡觉模式下,Alarms仍保持活跃,可以随意得叫醒设备。当设备重启的时候,所有的Alarms都会被取消。
通过AlarmManager来处理Alarm的操作.
获取AlarmManager:
AlarmManager alarmManager =
(AlarmManager)getSystemService(Context.ALARM_SERVICE);
创建一个新的 一次性的 Alarm,使用set方法,然后再指定Alarm类型,一个触发的时间,和一个 Pending Intent。
如果你规定的触发时间已经过了,那么这个Alarm会马上触发。
下面介绍类型:
1.RTC_WAKEUP 叫醒设备,触发Alarm(在指定的时间点,发送Pending Intent)。
2.RTC 不叫醒设备,触发Alarm(在指定的时间点,发送Pending Intent)。
3.ELAPSED_REALTIME 不叫醒设备。在一定的时间流逝后,触发Alarm。
4.ELAPSED_REALTIME_WAKEUP 叫醒设备。在一定的时间流逝后,触发Alarm。
你的这些类型选择会决定set方法内传的时间是准确的时间还是需要等待的时间。
例子:创建一个等待的ALARM,10秒后触发
// Get a reference to the Alarm Manager
AlarmManager alarmManager =
(AlarmManager)getSystemService(Context.ALARM_SERVICE);
// Set the alarm to wake the device if sleeping.
int alarmType = AlarmManager.ELAPSED_REALTIME_WAKEUP;
// Trigger the device in 10 seconds.
long timeOrLengthofWait = 10000;
// Create a Pending Intent that will broadcast and action
String ALARM_ACTION =ALARM_ACTION ;
Intent intentToFire = new Intent(ALARM_ACTION);
PendingIntent alarmIntent = PendingIntent.getBroadcast(this, 0,
intentToFire, 0);
// Set the alarm
alarmManager.set(alarmType, timeOrLengthofWait, alarmIntent);
纠正一点:这里的流逝的时间是相对的,当系统刚启动的时候是0,而你测试的时候系统已经在启动了10秒肯定早过了,所以你需要SystemClock.elapsedRealtime()获取系统已经流逝的时间再加上10秒也就是10000。
取消一个Alarm
alarmManager.cancel(alarmIntent);
设置重复的Alarms
1.setRepeating 准确的重复时间间隔
2.setInexactRepeating 不准确的。。。。
指定些常量:
1.INTERVAL_FIFTEEN_MINUTES
2.INTERVAL_HALF_HOUR
3.INTERVAL_HOUR
4.INTERVAL_HALF_DAY
5.INTERVAL_DAY
使用inexact repeating alarms,可以用来阻止多个APP分开唤醒设备在一个相似但是不重叠的时间。通过同步这些alarms,使系统有能力去减少重复事件给电池带来的消耗。
// Get a reference to the Alarm Manager
AlarmManager alarmManager =
(AlarmManager)getSystemService(Context.ALARM_SERVICE);
// Set the alarm to wake the device if sleeping.
int alarmType = AlarmManager.ELAPSED_REALTIME_WAKEUP;
// Schedule the alarm to repeat every half hour.
long timeOrLengthofWait = AlarmManager.INTERVAL_HALF_HOUR;
// Create a Pending Intent that will broadcast and action
String ALARM_ACTION =ALARM_ACTION ;
Intent intentToFire = new Intent(ALARM_ACTION);
PendingIntent alarmIntent = PendingIntent.getBroadcast(this, 0,
intentToFire, 0);
// Wake up the device to fire an alarm in half an hour, and every
// half-hour after that.
alarmManager.setInexactRepeating(alarmType,
timeOrLengthofWait,
timeOrLengthofWait,
alarmIntent);