博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
android的IntentService
阅读量:5882 次
发布时间:2019-06-19

本文共 6261 字,大约阅读时间需要 20 分钟。

  hot3.png

不管是何种Service,它默认都是在应用程序的主线程(亦即UI线程)中运行的。所以,如果你的Service将要运行非常耗时或者可能被阻塞的操作时,你的应用程序将会被挂起,甚至会出现ANR错误。为了避免这一问题,你应该在Service中重新启动一个新的线程来进行这些操作。现有两种方法共大家参考:

① 直接在Service的onStartCommand()方法中重启一个线程来执行,如:

@Override	public int onStartCommand(Intent intent, int flags, int startId) {		MyServiceActivity.updateLog(TAG + " ----> onStartCommand()");		new Thread(new Runnable() {			@Override			public void run() {				// 此处进行耗时的操作,这里只是简单地让线程睡眠了1s				try {					Thread.sleep(1000);				} catch (Exception e) {					e.printStackTrace();				}			}		}).start();		return START_STICKY;	}

② Android SDK 中为我们提供了一个现成的Service类来实现这个功能,它就是IntentService,它主要负责以下几个方面:

Creates a default worker thread that executes all intents delivered to   separate from your application's main thread.

    生成一个默认的且与主线程互相独立的工作者线程来执行所有传送至 onStartCommand() 方法的Intetnt

Creates a work queue that passes one intent at a time to your   implementation, so you never have to worry about multi-threading.

    生成一个工作队列来传送Intent对象给你的onHandleIntent()方法,同一时刻只传送一个Intent对象,这样一来,你就不必担心多线程的问题。

Stops the service after all start requests have been handled, so you never have to call  .

    在所有的请求(Intent)都被执行完以后会自动停止服务,所以,你不需要自己去调用stopSelf()方法来停止该服务

Provides default implementation of   that returns null.

    提供了一个onBind()方法的默认实现,它返回null

Provides a default implementation of   that sends the intent to the work queue and then to your   implementation

    提供了一个onStartCommand()方法的默认实现,它将Intent先传送至工作队列,然后从工作队列中每次取出一个传送至onHandleIntent()方法,在该方法中对Intent对相应的处理

以上,英文来自官方SDK,中文为我所译。

 从以上看来,你所需要做的就是实现 onHandleIntent() 方法,在该方法内实现你想进行的操作。另外,继承IntentService时,你必须提供一个无参构造函数,且在该构造函数内,你需要调用父类的构造函数,如下:

 
public HelloIntentService() {          super("HelloIntentService");  }

下面给出一例,来解释一下:

Activity部分: 
package com.archer.rainbow;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.ScrollView;import android.widget.TextView;public class MyServiceActivity extends Activity {	private static final String TAG = "MyServiceActivity";	private Button startSer1;	private Button stopSer1;	private Button startSer2;	private Button stopSer2;	private static TextView log;	private Intent intent;	private static ScrollView logView;	@Override	public void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		setContentView(R.layout.main);		startSer1 = (Button) findViewById(R.id.startSer1);		stopSer1 = (Button) findViewById(R.id.stopSer1);		startSer2 = (Button) findViewById(R.id.startSer2);		stopSer2 = (Button) findViewById(R.id.stopSer2);		log = (TextView) findViewById(R.id.log);		logView = (ScrollView) findViewById(R.id.logView);		startSer1.setOnClickListener(btnListener);		stopSer1.setOnClickListener(btnListener);		startSer2.setOnClickListener(btnListener);		stopSer2.setOnClickListener(btnListener);		intent = new Intent(MyServiceActivity.this, IntentServiceDemo.class);		// 打印出主线程的ID		long id = Thread.currentThread().getId();		updateLog(TAG + " ----> onCreate() in thread id: " + id);	}	private OnClickListener btnListener = new OnClickListener() {		@Override		public void onClick(View v) {			switch (v.getId()) {				case R.id.startSer1:					updateLog("Start Service 1 pressed");					startService(intent);					break;				case R.id.startSer2:					updateLog("Start Service 2 pressed");					startService(intent);					break;				case R.id.stopSer1:					updateLog("Stop Service 1 pressed");					stopService(intent);					break;				case R.id.stopSer2:					updateLog("Stop Service 2 pressed");					stopService(intent);					break;				default:					break;			}		}	};	public static void updateLog(final String text) {		log.post(new Runnable() {			@Override			public void run() {				CharSequence ch = log.getText();				log.setText(((ch == null || ch.length() == 0) ? text : ch						.toString()						+ "\r\n" + text));			}		});		logView.post(new Runnable() {			@Override			public void run() {				logView.fullScroll(ScrollView.FOCUS_DOWN);			}		});	}}

 Service部分了:

// service 代码package com.archer.rainbow;import java.text.SimpleDateFormat;import java.util.Date;import android.app.IntentService;import android.content.Intent;public class IntentServiceDemo extends IntentService {	private static final String TAG = "IntentServiceDemo";	private static final SimpleDateFormat SDF_DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss.SSS");	public IntentServiceDemo() {		super(TAG);		MyServiceActivity.updateLog(TAG + " ----> constructor");	}	@Override	public void onCreate() {		super.onCreate();		// 打印出该Service所在线程的ID		long id = Thread.currentThread().getId();		MyServiceActivity.updateLog(TAG + " ----> onCreate() in thread id: "				+ id);	}	@Override	public void onDestroy() {		super.onDestroy();		MyServiceActivity.updateLog(TAG + " ----> onDestroy()");	}	@Override	public int onStartCommand(Intent intent, int flags, int startId) {		MyServiceActivity.updateLog(TAG + " ----> onStartCommand()");		// 记录发送此请求的时间		intent.putExtra("time", System.currentTimeMillis());		return super.onStartCommand(intent, flags, startId);	}	@Override	public void setIntentRedelivery(boolean enabled) {		MyServiceActivity.updateLog(TAG + " ----> setIntentRedelivery()");		super.setIntentRedelivery(enabled);	}	@Override	protected void onHandleIntent(Intent intent) {		// 打印出处理intent所用的线程的ID		long id = Thread.currentThread().getId();		MyServiceActivity.updateLog(TAG				+ " ----> onHandleIntent() in thread id: " + id);		long time = intent.getLongExtra("time", 0);		Date date = new Date(time);		try {			// 打印出每个请求对应的触发时间			MyServiceActivity.updateLog(TAG					+ " ----> onHandleIntent(): 下载文件中..." + SDF_DATE_FORMAT.format(date));			Thread.sleep(3000);		} catch (InterruptedException e) {			e.printStackTrace();		}	}}

应用启动时,界面如下:

 

从此图可以看出,主线程(UI线程)的ID是1。接,连续点击三次Start Service 1 按钮,得如下画面:

 

从此图中可以看出,IntentServiceDemo的onCreate()所处的线程ID仍为1,说明它是在主线程中被执行的,且只被执行一次。然后,我每点击一次按钮,它都会触发一下onStartCommand()方法。仔细看第二次与第三次的onCommand()方法以及onHandleIntent()打印出来的语句,你会发现,第二、三两次点击按钮与第一次点击按钮的时间是没有超过3秒钟的,它们是连续被执行的,这说明了什么呢?说明,在第一个intent被处理时(即onHandleIntent()处于运行中),该Service仍然可以接受新的请求,但接受到新的请求后并没有立即执行,而是将它们放入了工作队列中,等待被执行。

这就是 IntentService 的简单用法。但你若是想在Service中让多个线程并发的话,就得另想法子喽。比如,使用第一种方法,在Service内部起多个线程,但是这样的话,你可要处理好线程的同步哦~~~ 

 

 

转载于:https://my.oschina.net/dsm/blog/126408

你可能感兴趣的文章
高性能 Oracle JDBC 编程
查看>>
java 中ResultSet可以获取的数据类型及返回值类型列表
查看>>
ubuntu 13 安装SH程序
查看>>
如何用几个简单的命令改善你的Linux安全
查看>>
查看MySQL记录执行过的SQL
查看>>
SpringMVC 之 国际化
查看>>
【转】Java并发编程73道面试题及答案
查看>>
你流量大吗?check_traffic.sh监控服务器流量
查看>>
java8 时间类与Date类的相互转化
查看>>
下半年过了中项,感谢学院,感谢薛老师,后面就跟着学院的各位老师学与考了
查看>>
RAID磁盘冗余阵列
查看>>
支付宝升级延时到账功能
查看>>
ghost后只剩下一个盘的数据寻回方法
查看>>
输入输出练习
查看>>
Git commit message和工作流规范
查看>>
java面试。答案源于网上
查看>>
yii中取得CActiveDataProvider的分页信息
查看>>
我的大学
查看>>
Google翻译接口收费啦
查看>>
Debian+Apache2服务器
查看>>