Android IntentService使用介绍以及源码解析

时间:2023-02-22 10:59:36

版权声明:本文出自汪磊的博客,转载请务必注明出处。

一、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比较简单,运行程序打印如下:

Android IntentService使用介绍以及源码解析

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使用介绍以及源码解析的更多相关文章

  1. Android HandlerThread使用介绍以及源码解析

    摘要: 版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.HandlerThread的介绍及使用举例              HandlerThread是什么鬼?其本质就是一个线程,但是Han ...

  2. IPerf——网络测试工具介绍与源码解析(4)

    上篇随笔讲到了TCP模式下的客户端,接下来会讲一下TCP模式普通场景下的服务端,说普通场景则是暂时不考虑双向测试的可能,毕竟了解一项东西还是先从简单的情况下入手会快些. 对于服务端,并不是我们认为的直 ...

  3. 【Android应用开发】EasyDialog 源码解析

    示例源码下载 : http://download.csdn.net/detail/han1202012/9115227 EasyDialog 简介 : -- 作用 : 用于在界面进行一些介绍, 说明; ...

  4. IPerf——网络测试工具介绍与源码解析(1)

    IPerf是一个开源的测试网络宽带并能统计并报告延迟抖动.数据包丢失率信息的控制台命令程序,通过参数选项可以方便地看出,通过设置不同的选项值对网络带宽的影响,对于学习网络编程还是有一定的借鉴意义,至少 ...

  5. Android Handler机制(四)---Handler源码解析

    Handler的主要用途有两个:(1).在将来的某个时刻执行消息或一个runnable,(2)把消息发送到消息队列. 主要依靠post(Runnable).postAtTime(Runnable, l ...

  6. Android Handler机制(二)---MessageQueue源码解析

    MessageQueue 1.变量 private final boolean mQuitAllowed;//表示MessageQueue是否允许退出 @SuppressWarnings(" ...

  7. IPerf——网络测试工具介绍与源码解析(2)

    对于IPerf源码解析,我是基于2.0.5版本在Windows下执行的情况进行分析的,提倡开始先通过对源码的简单修改使其能够在本地编译器运行起来,这样可以打印输出一些中间信息,对于理解源码的逻辑,程序 ...

  8. Android Handler机制(三)----Looper源码解析

    一.Looper Looper对象,顾名思义,直译过来就是循环的意思,从MessageQueue中不断取出message. Class used to run a message loop for a ...

  9. 【转载】Android IntentService使用全面介绍及源码解析

    一 IntentService介绍 IntentService定义的三个基本点:是什么?怎么用?如何work? 官方解释如下: //IntentService定义的三个基本点:是什么?怎么用?如何wo ...

随机推荐

  1. jQuery-template.js学习

    花了点时间,看了下jQuery-template.js,不多废话,先上结构 jQuery.each({..},function(){}) jQuery.fn.extend({..}) jQuery.e ...

  2. GJM :动作手游实时PVP 帧同步(客户端)[转载]

    原帖地址:http://gad.qq.com/article/detail/7171195 原文作者:唐声福  原帖备注:版权所有,禁止匿名转载:禁止商业使用:禁止个人使用. 1.概述 1.1.基于U ...

  3. Sharepoint学习笔记—习题系列--70-576习题解析 -(Q121-Q123)

    Question  121 You are designing a SharePoint 2010 workflow that will be used to monitor invoices. Th ...

  4. 看守所、戒毒所3D指纹门禁系统解决方案

    为响应"科技强警"的战略方针,华本构建了一个完整的.集成的.可靠的.易操作的高安全性门禁系统,应用于看守所.戒毒所.*局和部队等单位,使管理更现代化.规范化,有效地预防和制止越狱 ...

  5. Winform软件,不要在线程里操作UI

    对于Winform软件,不要在线程里操作UI,不要相信:StartForm.CheckForIllegalCrossThreadCalls = false; 于是,把所有的代码都改成主线程委托调用的方 ...

  6. Hadoop2.4代码的坑

    org.apache.hadoop.hdfs.server.datanode.BlockPoolManager 和org.apache.hadoop.hdfs.server.datanode.Data ...

  7. ubuntu 14.04解决gedit中文乱码的问题

    终端输入 gsettings set org.gnome.gedit.preferences.encodings auto-detected "['UTF-8','GB18030','GB2 ...

  8. Android-支付宝快捷支付

    支付宝的快捷支付Android版业务流程比較麻烦,出现的意外情况比較多.在此,简单说下开发流程以及出现错误的解决方式; 1.注冊支付业务.这里不在赘述.建立数据安全传输所须要的私钥公钥,这里採用的是R ...

  9. Vijos P1066 弱弱的战壕【多解,线段树,暴力,树状数组】

    弱弱的战壕 描述 永恒和mx正在玩一个即时战略游戏,名字嘛~~~~~~恕本人记性不好,忘了-_-b. mx在他的基地附近建立了n个战壕,每个战壕都是一个独立的作战单位,射程可以达到无限(“mx不赢定了 ...

  10. dp之背包总结篇

    //新手DP学习中 = =!! 前言:背包问题在dp中可以说是经典,作为一个acmer,到现在才正式学习dp,可以说是比较失败的.我个人比较认同一点,想要做一个比较成功的acmer,dp.搜索.数学必 ...