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

本文详细介绍了如何在Android应用中利用后台线程、AsyncTask、Service组件、CursorLoader等工具进行高效的数据处理和操作,特别强调了如何避免UI线程的阻塞,并通过实例演示了如何创建和运行AsyncTask,以及如何使用IntentService实现批量任务处理。同时,文章还介绍了Loader机制、使用alarms进行定时任务以及如何合理设置alarms以减少资源消耗和优化设备唤醒机制。通过这些方法,开发者可以显著提升Android应用的性能和用户体验。

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

相应能力对于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.onPostExecutedoInBackground完成的时候,它的返回值会作为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);

 

转载于:https://my.oschina.net/wangjunhe/blog/113308

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值