Android面试题Service,Android面试题-IntentService源码分析
自定义控件
联网
工具
数据库
源码分析相关面试题
Activity相关面试题
Service相关面试题
与XMPP相关面试题
与性能优化相关面试题
与登录相关面试题
与开发相关面试题
与人事相关面试题
人事面试宝典
IntentService是继承于Service并处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动IntentService的方式和启动传统Service一样,同时,当任务执行完后,IntentService会自动停止,而不需要我们去手动控制。另外,可以启动IntentService多次,而每一个耗时操作会以工作队列的方式在IntentService的onHandleIntent回调方法中执行,并且,每次只会执行一个工作线程,执行完第一个再执行第二个,以此类推。
而且,所有请求都在一个单线程中,不会阻塞应用程序的主线程(UI Thread),同一时间只处理一个请求。
IntentService有什么好处呢?
1)我们省去了在Service中手动开线程的麻烦,
2)当操作完成时,我们不用手动停止Service。
接下来让我们来看看如何使用,写一个Demo来模拟两个耗时操作,Operation1与Operation2,先执行1,2必须等1执行完才能执行2:
新建工程,新建一个继承IntentService的类,我这里是IntentServiceDemo.java
public class IntentServiceDemo extends IntentService {
public IntentServiceDemo() {
//必须实现父类的构造方法
super("IntentServiceDemo");
}
@Override
public IBinder onBind(Intent intent) {
System.out.println("onBind");
return super.onBind(intent);
}
@Override
public void onCreate() {
System.out.println("onCreate");
super.onCreate();
}
@Override
public void onStart(Intent intent, int startId) {
System.out.println("onStart");
super.onStart(intent, startId);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void setIntentRedelivery(boolean enabled) {
super.setIntentRedelivery(enabled);
System.out.println("setIntentRedelivery");
}
@Override
protected void onHandleIntent(Intent intent) {
//Intent是从Activity发过来的,携带识别参数,根据参数不同执行不同的任务
System.out.println("currentThread()=" + Thread.currentThread().getName());
String action = intent.getExtras().getString("param");
if (action.equals("oper1")) {
System.out.println("Operation1");
}else if (action.equals("oper2")) {
System.out.println("Operation2");
}
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void onDestroy() {
System.out.println("onDestroy");
super.onDestroy();
}
}
我把生命周期方法全打印出来了,待会我们来看看它执行的过程是怎样的。接下来是Activity,在Activity中来启动IntentService:
public class TestActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//可以启动多次,每启动一次,就会新建一个work thread,但IntentService的实例始终只有一个
//Operation 1
Intent startServiceIntent = new Intent("com.test.intentservice");
Bundle bundle = new Bundle();
bundle.putString("param", "oper1");
startServiceIntent.putExtras(bundle);
startService(startServiceIntent);
//Operation 2
Intent startServiceIntent2 = new Intent("com.test.intentservice");
Bundle bundle2 = new Bundle();
bundle2.putString("param", "oper2");
startServiceIntent2.putExtras(bundle2);
startService(startServiceIntent2);
}
}
最后,别忘了配置Service,因为它继承于Service,所以,它还是一个Service,一定要配置,否则是不起作用的
最后来看看执行结果:
从结果可以看到,onCreate方法只执行了一次,而onStartCommand和onStart方法执行了两次,开启了两个Work Thread,这就证实了之前所说的,启动多次,但IntentService的实例只有一个,这跟传统的Service是一样的。Operation1也是先于Operation2打印,并且我让两个操作间停顿了2s,最后是onDestroy销毁了IntentService。
IntentService 源码分析
@Override
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
源码可知:
1)实际上是使用了一个 HandlerThread 来维护线程的,
2) HandleThread 中,内部已经维护一个 Looper,这里直接使用 HandlerThread 的 Looper 对象,便于在 IntentService 中去维护消息队列,
3)创建的 mServiceHandler 是属于 HandleThread 这个 WorkerThread 的。
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);
}
}
源码可知:
1)直接把消息交给 onHandleIntent() 方法去执行具体的业务逻辑
2)执行完成之后,立即调用 stopSelf() 方法停止自己
接下来分析start源码
@Override
public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
源码可知
1)在 onStartCommand() 中直接调用了 onStart() 方法
2)而上面 stopSelf() 方法使用的 startId 来停止当前的此次任务服务。
3)而 Service 如果被启动多次,就会存在多个 startId ,当所有的 startId 都被停止之后,才会调用 onDestory() 自我销毁。
我们在看看HandlerThread启动之后的源码
@Override
public void run() {
mTid = Process.myTid();
Looper.prepare();
synchronized (this) {
mLooper = Looper.myLooper();
notifyAll();
}
Process.setThreadPriority(mPriority);
onLooperPrepared();
Looper.loop();
mTid = -1;
}
源码可知
1)run方法里面添加了锁,这也解释了为什么多次 start 同一个 IntentService 它会顺序执行,全部执行完成之后,再自我销毁。
欢迎关注微信公众号,长期推荐技术文章和技术视频
微信公众号名称:Android干货程序员
Android面试题Service,Android面试题-IntentService源码分析相关推荐
- Android 异步处理之IntentService源码分析
本文授权发布公众号[刘桂林],星球[Hi Android] 今天介绍一下IntentService,他和Service其实差不多,只是内部实现了一个HandlerThread,这点我们看源码其实就可以 ...
- Android Retrofit 2.0(三)从源码分析原理
Retrofit·特点 性能最好,处理最快 使用REST API时非常方便: 传输层默认就使用OkHttp: 支持NIO: 拥有出色的API文档和社区支持 速度上比volley更快: 如果你的应用程序 ...
- Android wifi探究二:Wifi framework层源码分析
上一篇博客初步认识了wpa_supplicant的作用和使用方法,并且尝试着梳理了wifi的大框架,不过,java层的框架我们忽略了,没有分析,也就是说上一篇博客简单的指出了wifi代码的大框架,那么 ...
- 【朝花夕拾】Android自定义View篇之(六)Android事件分发机制(中)从源码分析事件分发机制...
前言 转载请注明,转自[https://www.cnblogs.com/andy-songwei/p/11039252.html]谢谢! 在上一篇文章[[朝花夕拾]Android自定义View篇之(五 ...
- 【朝花夕拾】Android自定义View篇之(六)Android事件分发机制(中)从源码分析事件分发逻辑及经常遇到的一些“诡异”现象
前言 转载请注明,转自[https://www.cnblogs.com/andy-songwei/p/11039252.html]谢谢! 在上一篇文章[[朝花夕拾]Android自定义View篇之(五 ...
- android如何创建进度条,Android控件ProgressBar--自定义进度条及源码分析
这里用SeekBar做演示,SeekBar继承自ProgressBar,拥有其一切特性,并且其支持拖动以及DPAD左右键的进退.一起学习吧! 一.自定义SeekBar进度条样式 原生SeekBar效果 ...
- Android 7.0 虚拟按键(NavigationBar)源码分析 之 点击事件的实现流程
第二部分: Let's go!!! [点击事件的实现流程] 1.初始化 虚拟按键点击效果的实现和实体按键相似,也是通过上报一个keyCode值,来判断哪个按钮被点击.不同的是,实体按键的keyCode ...
- Android车载系统(HVAC) 原理+源码分析(代码示例)
前言 Android车载系统(HVAC)是一种用于控制车内温度.空气质量和湿度的系统,它是一项重要的汽车电子技术.在这种系统中,CarHvacManager控制器是一个重要的组件,它通过与车载传感器和 ...
- android framework车载桌面CarLauncher的TaskView详细源码分析
1.构建相关的TaskView,装载到对应的ViewGroup b站免费视频教程讲解: https://www.bilibili.com/video/BV1wj411o7A9/ //packages/ ...
最新文章
- 程序员如何避免陷入内卷?
- python mysql example_Python_Example_ Pycharm(python) 与 数据库(MySQL) 连接学习/示例
- 带有Spring和Maven教程的JAX–WS
- SQL Server与Oracle、DB2三种数据库比较
- 深入了解crc32算法
- python能做什么工作-python语言能做什么工作
- ubuntu上解决evolution邮箱附件为dat格式
- Linux 文件权限、用户权限和用户组管理vim的一些基本使用技巧
- refprop物性库_REFPROP下载-REFPROP官方版下载[制冷剂物性查询]-天极下载
- 卷积神经网络如何进行图像识别的
- m4a录音文件损坏修复_m4a音频文件损坏修复!
- 度量python的运行时间
- 无老师作文巨讲堂2015.8
- 简述完整的计算机组成部分组成部分组成,简述计算机系统的组成
- 是否应该选择虚拟主机?
- 弗洛伊德算法思想理解
- 2021年度总结 -- 万粉博主的写作荣誉分享,写博客是一种心灵的修行
- 北大邹磊:图数据库中的子图匹配算法
- 小白学GAN系列2——nn.ReLU与nn.LeakyReLU的区别
- 计算机会考作业,计算机会考Excel操作题作业文档.doc
热门文章
- [渝粤教育] 中国海洋大学 求职OMG 参考 资料
- 【渝粤教育】电大中专药剂学基础知识 (3)作业 题库
- 【渝粤教育】电大中专电商运营实操 (18)作业 题库
- 【渝粤题库】国家开放大学2021春3962金融营销基础题目
- 低功耗远距离lora模块:SX1262与SX1278、SX1276射频无线收发器芯片对比分析以及选型指南
- 与kylin_什么是Kylin,Kylin的学习
- spring mail 发送html simple,SpringBoot整合Mail邮件发送
- 怎么在html中加入pjax,pjax加载多说的三种方法
- ecshop 模板 php代码,ecshop无法在模板文件.dwt和.lbi中直接添加php代码的解决方法...
- 高斯信道、单径Rayleigh信道和多径衰落信道下基带模型的多用户BPSK直接序列扩频系统MATLAB仿真(m序列、Gold序列和正交Gold序列)