Android-工作在后台-使用后台线程

本文介绍了Android应用中如何处理后台任务,包括使用AsyncTask进行短期处理、IntentService执行一系列任务及Loader优化ContentProvider查询等方法。此外,还讲解了如何利用Alarms在特定时间触发事件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

相应能力对于Android系统来说太重要了。为了确保APP快速地应对用户的交互和系统事件,我们需要将所有的耗时处理和I/O相关的操作移到子线程中去。

文件操作、网络查询、数据库事务、还有复杂的计算都应该在后台线程中进行。

Android提供了一系列的措施可以让你将处理移到后台。

比如:Thread+Handler的组合,AsyncTask。

AsyncTask用来执行短期的处理非常合适。但是呢,Activity重启的时候,它是不会有所保留的。比如说设备配置发生改变,导致Activity重启,然后AsyncTask就会被打断。

通常推荐,那种相对更长时间操作的,可以选择Service组件。

相似的,CursorLoader用来优化ContentProvider的查询非常合适。

 

创建新的AsyncTask

每个建立的AsyncTask都需要指定3个泛型参数类型,第一个:输入的参数,第二个:进度值,第三个:结果值。

下面直接看例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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是在后台线程的:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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秒后触发

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 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,使系统有能力去减少重复事件给电池带来的消耗

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 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);

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值