Android IntentService使用介绍以及源码解析
版权声明:本文出自汪磊的博客,转载请务必注明出处。
一、IntentService概述及使用举例
IntentService内部实现机制用到了HandlerThread,如果对HandlerThread不了解的话建议先看上篇文章:Android HandlerThread使用介绍以及源码解析。
IntentService是神马玩意?它就是一个Service,但是我们知道在Service中不能进行耗时操作,如果要进行耗时操作的话我们就需要自己new一个子线程在里面进行耗时操作,然而这一切谷歌工程师早就替我们做好了,只需使用IntentService即可,自己会启动一个子线程做耗时操作,无需我们自己管理子线程,并且完成任务后会自动停止。这么好的玩意赶紧看下怎么使用。
接下来我们编写一个小Demo,模拟在IntentService中进行网络通信,并且成功后通知主线程,主线程做出相应反应。Demo中通过广播接收者实现子线程与主线程的通信。
首先我们编写IntentService,如下:
public class MyIntentService extends IntentService {
public static final String TAG = "WL";
public MyIntentService() {
//为子线程起一个名字
super("IntentService");
}
//子线程中执行
@Override
protected void onHandleIntent(Intent intent) {
// TODO Auto-generated method stub
if(null !=intent){
String action = intent.getAction();
if(action.equalsIgnoreCase(MainActivity.ACTION_START)){
String url = intent.getStringExtra(MainActivity.URL);
Log.i(TAG, "开始请求_URL:"+url);
//模拟网络请求
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.i(TAG, "请求成功");
//
handlerRequestSuccess();
}
}
}
//
private void handlerRequestSuccess() {
// 发送广播通知主线程请求成功
Intent intent = new Intent(MainActivity.ACTION_START);
intent.putExtra("msg", "请求成功");
sendBroadcast(intent);
}
}
主要逻辑就是继承IntentService,重写onHandleIntent方法,onHandleIntent运行在子线程可以进行耗时操作,在模拟网络请求成功的时候发送广播。
接下来看下MainActivity逻辑:
public class MainActivity extends Activity {
//
public static final String ACTION_START= "START_HTTP_REQUEST";
public static final String URL= "URL";
private MyBroadcastReceiver myBroadcastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//注册广播接收者
myBroadcastReceiver = new MyBroadcastReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_START);
registerReceiver(myBroadcastReceiver, filter);
}
@Override
protected void onResume() {
//
super.onResume();
Intent intent = new Intent(this, MyIntentService.class);
intent.setAction(ACTION_START);
intent.putExtra(URL, "http://www.cnblogs.com/leipDao/");
startService(intent);//必须是start方式启动服务,bind方法无效,分析源码的时候就明白了
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
unregisterReceiver(myBroadcastReceiver);
}
private class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if(action.equalsIgnoreCase(ACTION_START)){
String extra = intent.getStringExtra("msg");
Log.i(MyIntentService.TAG, "onReceive::::"+extra);
}
}
}
}
逻辑也是比较简单,onCreate的时候注册广播接收者,用于接收IntentService中模拟网络请求成功的时候发送的广播,onResume的时候启动服务。onDestroy的时候移除广播接收者。Demo比较简单,运行程序打印如下:

IntentService中完成耗时操作并且完成子线程与主线程的通信。
二、IntentService源码解析
IntentService源码比较简短,直接贴出全部源码分析:
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private String mName;
private boolean mRedelivery;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public IntentService(String name) {
super();
mName = name;
}
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
@Override
public void onCreate() {
// TODO: It would be nice to have an option to hold a partial wakelock
// during processing, and to have a static startService(Context, Intent)
// method that would launch the service & hand off a wakelock.
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
/**
* You should not override this method for your IntentService. Instead,
* override {@link #onHandleIntent}, which the system calls when the IntentService
* receives a start request.
* @see android.app.Service#onStartCommand
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onDestroy() {
mServiceLooper.quit();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@WorkerThread
protected abstract void onHandleIntent(Intent intent);
}
很简短吧,出去注释不到100行,接下来我们分析重点部分。
24-27行,构造函数传递进来一个name,用于第40行初始化HandlerThread,就是子线程的名字。
接下来看34-45行onCreate()的时候:主要就是初始化一个HandlerThread以及ServiceHandler,7-17行发现ServiceHandler就是一个普通的Handler而已。看过上一篇Android HandlerThread使用介绍以及源码解析应该明白,ServiceHandler运行在子线程中,这里就不仔细解释了,不明白的地方可以查看Android HandlerThread使用介绍以及源码解析。
73-75行发现onBind的时候什么也没做,就是返回null,还记得demo中注释吗必须以start方式启动服务,因为bing方式启动什么也没做。
48-53行onStart的时候发送一个消息到ServiceHandler,第14行handleMessage的时候直接调用onHandleIntent方法,紧接着15行结束本次任务。
到这里主要流程就完了,其本质就是利用了HandlerThread保证ServiceHandler在子线程运行机制,在我们以start方式启动服务的时候,执行到service生命周期方法onStart的时候就会发送一个消息,然后在ServiceHandler中handleMessage方法执行onHandleIntent方法,子类重写此方法实现耗时任务即可。
好了,到此IntentService就分析完了,理解IntentService最核心的就是先理解HandlerThread。
本篇到此为止,希望对你有用。
Android IntentService使用介绍以及源码解析的更多相关文章
- Android HandlerThread使用介绍以及源码解析
摘要: 版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.HandlerThread的介绍及使用举例 HandlerThread是什么鬼?其本质就是一个线程,但是Han ...
- IPerf——网络测试工具介绍与源码解析(4)
上篇随笔讲到了TCP模式下的客户端,接下来会讲一下TCP模式普通场景下的服务端,说普通场景则是暂时不考虑双向测试的可能,毕竟了解一项东西还是先从简单的情况下入手会快些. 对于服务端,并不是我们认为的直 ...
- 【Android应用开发】EasyDialog 源码解析
示例源码下载 : http://download.csdn.net/detail/han1202012/9115227 EasyDialog 简介 : -- 作用 : 用于在界面进行一些介绍, 说明; ...
- IPerf——网络测试工具介绍与源码解析(1)
IPerf是一个开源的测试网络宽带并能统计并报告延迟抖动.数据包丢失率信息的控制台命令程序,通过参数选项可以方便地看出,通过设置不同的选项值对网络带宽的影响,对于学习网络编程还是有一定的借鉴意义,至少 ...
- Android Handler机制(四)---Handler源码解析
Handler的主要用途有两个:(1).在将来的某个时刻执行消息或一个runnable,(2)把消息发送到消息队列. 主要依靠post(Runnable).postAtTime(Runnable, l ...
- Android Handler机制(二)---MessageQueue源码解析
MessageQueue 1.变量 private final boolean mQuitAllowed;//表示MessageQueue是否允许退出 @SuppressWarnings(" ...
- IPerf——网络测试工具介绍与源码解析(2)
对于IPerf源码解析,我是基于2.0.5版本在Windows下执行的情况进行分析的,提倡开始先通过对源码的简单修改使其能够在本地编译器运行起来,这样可以打印输出一些中间信息,对于理解源码的逻辑,程序 ...
- Android Handler机制(三)----Looper源码解析
一.Looper Looper对象,顾名思义,直译过来就是循环的意思,从MessageQueue中不断取出message. Class used to run a message loop for a ...
- 【转载】Android IntentService使用全面介绍及源码解析
一 IntentService介绍 IntentService定义的三个基本点:是什么?怎么用?如何work? 官方解释如下: //IntentService定义的三个基本点:是什么?怎么用?如何wo ...
随机推荐
- Python Linear algebra
Linear algebra 1.模块文档 NAME numpy.linalg DESCRIPTION Core Linear Algebra Tools ---------------------- ...
- YYHS-分数(二分+容斥)
题目描述 KJDH是个十分善于探索的孩子,有一天他把分子分母小于等于n的最简分数列在了纸上,他想找到这些分数里第k小的数,这对于KJDH来说当然是非常轻易,但是KJDH最近多了很多妹子,他还要去找妹子 ...
- Windows环境下多线程编程原理与应用读书笔记(6)————临界段及其应用
<一>临界段 临界段对象通过提供所有线程必须共享的对象来控制线程.只有拥有临界段对象的线程才能够访问保护的资源.在另一个线程可以访问该资源之前,前一线程必须释放临界段对象,一遍新的线程可以 ...
- poj 2486 Apple Tree(树形DP 状态方程有点难想)
Apple Tree Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9808 Accepted: 3260 Descri ...
- D3.js从入门到“放弃”指南
前言 近期略有点诸事不顺,趁略有闲余之时,玩起D3.js.之前实际项目中主要是用各种chart如hightchart.echarts等,这些图形库玩起来貌都是完美的,一切皆可配置,但几年前接触了D3之 ...
- idea 配置tomcat(包含tomcat Server找不到的配置方法)
在配置tomcate时有时候按照网上说的找不到tomcat Server,不知不觉花了很长时间这时我们在这里配置就可以了如图所示 1.这是有tomcat Server的配置(后面是没有的情况下的配置) ...
- Android 开发笔记___DateUtil——Time
package com.example.alimjan.hello_world; /** * Created by alimjan on 6/30/2017. */ import java.text. ...
- kafka学习笔记2:生产者
这次的笔记主要记录一下kafka的生产者的使用和一些重要的参数. 文中主要截图均来自kafka权威指南 主要涉及到两个类KafkaProducer和ProducerRecord. 总览 生产者的主要架 ...
- 如何在ASP.NET Core Web API测试中使用Postman
使用Postman进行手动测试 如果您是开发人员,测试人员或管理人员,则在构建和使用应用程序时,有时了解各种API方法可能是一个挑战. 使用带有.NET Core的Postman为您的Web API生 ...
- 漫淡面向对象——POJO对象
产品或者服务由数据存储和数据计算组成.pojo对象就是用于数据存储.一旦确定后,整个应用或者产品的数据来源就确定.比如一个页面或者功能需要使用什么数据就可以快速找到对应的对象或者通过对象的关系找出来. ...