写在前面

该博客思路源于在简书看到goeasyway博主写的Android面试一天一题系列,无copy之意,仅为让自己总结知识点,成长一点点。先感谢各位大神的无私分享~!

关于题目,大部分则出自AndroidInterview-Q-ALearningNotes,当然既然是Android面试,主要是Android部分,Java基础之后再写。

IntentService作用是什么,AIDL解决了什么问题 — 小米

想知道IntentService的作用,当然需要先了解何为IntentService。

IntentService

官方解释是这样说的:

IntentService是一个基于Service的子类,其能够根据需求处理异步请求(作为Intent一样来表示)。客户端通过startService(Intent)发送异步请求调用;服务作为需要而开始,控制每个Intent来转向使用一个工作线程,并且当工作完成后自己会停止。

这个工作队列处理器部分通常用于从应用的主线程卸下任务IntentService类纯在为了简化这个部分和考虑到了mechanics。为了使用它,扩展IntentService和实现onHandleIntent(Intent)。IntentService会收到Intents,启动一个工作线程和恰当地停止服务。

所有请求被耽搁工作线程控制 — 他们可能只需要(切不会阻塞应用主线程),但每次只处理一个请求。

先抛开官方解释不说,其实我们应该想想为什么有了Service还需要一个IntentService呢?这里就引出Service与IntentService之间的区别,那么两者是否应该有联系,区别又是什么呢?考虑问题时我们应该往深度和广度去探索,当然别太深无法自拔最后自己都不知道想要了解什么问题。所以接下来的几个问题:

Service的弊端?为什么会出现IntentService,Service和IntentService的区别?

如果说Service是依附于主线程的,也就是说不能进行耗时操作,而继承于它的子类IntentService中新增了哪些代码呢,这就可以从源码入手了,下面是IntentService的几个重要元素:

public abstract class IntentService extends Service {
// Looper可以知道需要与handler的套用,进行MessageQueue的资源存放和索取
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
// ... 代码省略 ... // 实际上也是通过Handler的机制来实现耗时操作
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);
}
} // ... 代码省略 ... @Override
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start(); // 从上面实例化的线程中获取Looper,然后再传入ServiceHandler
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
} // ... 代码省略 ... /**
* This method is invoked on the worker thread with a request to process.
* Only one Intent is processed at a time, but the processing happens on a
* worker thread that runs independently from other application logic.
* So, if this code takes a long time, it will hold up other requests to
* the same IntentService, but it will not hold up anything else.
* When all requests have been handled, the IntentService stops itself,
* so you should not call {@link #stopSelf}.
*
* @param intent The value passed to {@link
* android.content.Context#startService(Intent)}.
*/
@WorkerThread
protected abstract void onHandleIntent(Intent intent);
}

注意onHandleIntent方法的注释:

该方法可以为唤起一个工作线程,而每次只能处理一个Intent,但是这个过程发生在工作线程中,并且运行在一个独立于其他的应用逻辑中,因此如果这部分代码会花一些时间的话,就会先拦截别的请求对于同一个IntentService,但不会拦截除此之外的事件。一旦所有请求都被处理了以后,IntentService会自动停止,你不需要调用stopSelf。

啰嗦一大堆,说白了IntentService就是为了实现让Service能够进行耗时操作的功能。

IntentService的用法

光知道概念和原理,但是不会用怎么行呢,我们以一个简单的Demo来进行示例,首先创建一个MainActivity负责事件开始,点击onClick的时候启动IntentService:

public class MainActivity extends AppCompatActivity {

    private boolean serviceRunning = false;

    @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView serviceStates = (TextView) findViewById(R.id.tv_service_states);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent serviceIntent = new Intent(MainActivity.this, CustomIntentService.class);
serviceIntent.putExtra("sleep_flag", true);
if (!serviceRunning) {
startService(serviceIntent);
serviceStates.setText("Service is running...");
} else {
stopService(serviceIntent);
serviceStates.setText("Service is stop...");
}
serviceRunning = !serviceRunning;
}
});
}
}
public class CustomIntentService extends IntentService {
public static final String TAG = CustomIntentService.class.getSimpleName(); public CustomIntentService() {
super("CustomIntentService");
} @Override
protected void onHandleIntent(Intent intent) {
Log.e(TAG, " onHandleIntent====> ");
boolean flag = intent.getBooleanExtra("sleep_flag", false);
Log.e(TAG, " onHandleIntent flag ====> " + flag);
} @Override
public void onCreate() {
Log.e(TAG, " onCreate ====> executed ");
super.onCreate();
} @Override
public void onDestroy() {
Log.e(TAG, " onDestroy ====> executed ");
super.onDestroy();
} @Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, " onStartCommand ====> executed ");
boolean flag = intent.getBooleanExtra("sleep_flag", false);
Log.e(TAG, " onStartCommand flag ====> " + flag);
return super.onStartCommand(intent, flags, startId);
} @Override
public IBinder onBind(Intent intent) {
Log.e(TAG, " onBind ====> executed ");
return super.onBind(intent);
} @Override
public boolean onUnbind(Intent intent) {
Log.e(TAG, " onUnbind ====> executed ");
return super.onUnbind(intent);
} @Override
public void onRebind(Intent intent) {
Log.e(TAG, " onRebind ====> executed "); super.onRebind(intent);
}
}

因为我在Intent中传递了一个boolean值作为标记,可以在下面的执行结果中看到IntentService方法的执行顺序:

E/CustomIntentService:  onCreate ====>  executed
E/CustomIntentService: onStartCommand ====> executed
E/CustomIntentService: onStartCommand flag ====> true
E/CustomIntentService: onHandleIntent====>
E/CustomIntentService: onHandleIntent flag ====> true
E/CustomIntentService: onDestroy ====> executed

当我在onHandleIntent()中使线程睡眠10s时,连续点击两次启动Button,可以看到并没有出现Service中ANR的问题,过了一会sleeping end才结束,因为IntentService通过新的子线程来进行耗时操作,从而不会影响主线程的业务逻辑。

@Override
protected void onHandleIntent(Intent intent) {
Log.e(TAG, " onHandleIntent====> ");
boolean flag = intent.getBooleanExtra("sleep_flag", false);
Log.e(TAG, " onHandleIntent flag ====> " + flag);
Log.e(TAG, " onHandleIntent====> sleeping start");
try {
Thread.sleep(10 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e(TAG, " onHandleIntent====> sleeping end");
}
// 第一次点击
E/CustomIntentService: onCreate ====> executed
E/CustomIntentService: onStartCommand ====> executed
E/CustomIntentService: onStartCommand flag ====> true
E/CustomIntentService: onHandleIntent====>
E/CustomIntentService: onHandleIntent flag ====> true
E/CustomIntentService: onHandleIntent====> sleeping start
E/CustomIntentService: onDestroy ====> executed
// 第二次点击
E/CustomIntentService: onCreate ====> executed
E/CustomIntentService: onStartCommand ====> executed
E/CustomIntentService: onStartCommand flag ====> true
E/CustomIntentService: onHandleIntent====>
E/CustomIntentService: onHandleIntent flag ====> true
E/CustomIntentService: onHandleIntent====> sleeping start
E/CustomIntentService: onDestroy ====> executed
// sleep结束
E/CustomIntentService: onHandleIntent====> sleeping end
E/CustomIntentService: onHandleIntent====> sleeping end

Android面试一天一题(1Day)的更多相关文章

  1. 2021大厂Android面试高频100题最新汇总(附答案详解)

    前言 现在越来越多的人应聘工作时都得先刷个几十百来道题,不刷题感觉都过不了面试. 无论是前后端.移动开发,好像都得刷题,这么多人通过刷题过了面试,说明刷题对于找工作还是有帮助的. 不过这其中有一个问题 ...

  2. android 面试准备基础题

    1.    请描述下Activity的生命周期. 必调用的三个方法:onCreate() --> onStart() --> onResume(),用AAA表示 )父Activity启动子 ...

  3. Android面试优雅地介绍自己的项目

    本文转载:m.blog.csdn.net/iamsamzhang/article/details/51916584 先说句题外话,很多公司16年秋招的内推已经开始啦,我目前知道的在北京有网易.百度和微 ...

  4. 2020年最新阿里、字节、腾讯、京东等一线大厂高频面试(Android岗)真题合集,面试轻松无压力

    本文涵盖了阿里巴巴.腾讯.字节跳动.京东.华为等大厂的Android面试真题,不管你是要面试大厂还是普通的互联网公司,这些面试题对你肯定是有帮助的,毕竟大厂一定是行发展的标杆,很多公司的面试官同样会研 ...

  5. Android开发如何准备技术面试(含Android面试押题)

    今年毋庸置疑是找工作的寒冬,每一个出来找工作的同学都是值得尊敬的.现在找工作,虽然略难,但是反过来看也会逼迫我们成为更加优秀的自己. 但是不管是旺季还是寒冬,有一些优秀的同学找工作还是挺顺利的.所以说 ...

  6. Android面试总结 (转)

    1. 下列哪些语句关于内存回收的说明是正确的? (b) A. 程序员必须创建一个线程来释放内存 B. 内存回收程序负责释放无用内存 C. 内存回收程序允许程序员直接释放内存 D. 内存回收程序可以在指 ...

  7. 【Android面试】Android面试题集锦 (陆续更新)(最新2012-6-18) eoe上看到的

    ===============eoeAndroid社区推荐:======================= 1.Android开发新浪面试题[开发者必看哦]下载地址 http://www.eoeand ...

  8. Android面试题目及其答案

    转自:http://blog.csdn.net/wwj_748/article/details/8868640 Android面试题目及其答案 1.Android dvm的进程和Linux的进程, 应 ...

  9. Android面试题目2

    1. 请描述下Activity的声明周期. onCreate->onStart->onRemuse->onPause->onStop->onRestart->onD ...

随机推荐

  1. 聊聊Unity项目管理的那些事:Git-flow和Unity

    0x00 前言 目前所在的团队实行敏捷开发已经有了一段时间了.敏捷开发中重要的一个话题便是如何对项目进行恰当的版本管理.项目从最初使用svn到之后的Git One Track策略再到现在的GitFlo ...

  2. MVC Core 网站开发(Ninesky) 2.1、栏目的前台显示

    上次创建了栏目模型,这次主要做栏目的前台显示.涉及到数据存储层.业务逻辑层和Web层.用到了迁移,更新数据库和注入的一些内容. 一.添加数据存储层 1.添加Ninesky.DataLibrary(与上 ...

  3. Zabbix基本配置及监控主机

    监控主机一版需要在被监控的主机上安装Zabbix Agent 监控主机 安装zabbix-agent 首先需要在被监控的主机上安装agent,可以下载预编译好的RPM进行安装,下载地址:http:// ...

  4. 通过微信小程序看前端

    前言 2016年9月22日凌晨,微信官方通过“微信公开课”公众号发布了关于微信小程序(微信应用号)的内测通知.整个朋友圈瞬间便像炸开了锅似的,各种揣测.介绍性文章在一夜里诞生.而真正收到内测邀请的公众 ...

  5. 6_Win7下Chrome主页被流氓网站hao123.com劫持后的解决方法。

    今天安装了一个PDF阅读器,免费的,你懂的,结果自己安装的时候没有将默认的选项取消,就被hao123流氓网站劫持啦. 说实话某免费PDF阅读器还算好的,有一个可以供你选择的项.不想某些软件直接就默认选 ...

  6. C#语法糖大汇总

    首先需要声明的是"语法糖"这个词绝非贬义词,它可以给我带来方便,是一种便捷的写法,编译器会帮我们做转换:而且可以提高开发编码的效率,在性能上也不会带来损失.这让java开发人员羡慕 ...

  7. prometheus监控系统

    关于Prometheus Prometheus是一套开源的监控系统,它将所有信息都存储为时间序列数据:因此实现一种Profiling监控方式,实时分析系统运行的状态.执行时间.调用次数等,以找到系统的 ...

  8. RabbitMQ + PHP (一)入门与安装

    RabbitMQ: 1.是实现AMQP(高级消息队列协议)的消息中间件的一种. 2.主要是为了实现系统之间的双向解耦而实现的.当生产者大量产生数据时,消费者无法快速消费,那么需要一个中间层.保存这个数 ...

  9. Hibernate 系列 学习笔记 目录 (持续更新...)

    前言: 最近也在学习Hibernate,遇到的问题差不多都解决了,顺便把学习过程遇到的问题和查找的资料文档都整理了一下分享出来,也算是能帮助更多的朋友们了. 最开始使用的是经典的MyEclipse,后 ...

  10. jexus5.8.2 linux x64专业版 配置https

    一.环境 1.jexus版本:Jexus/5.8.2.8 Linux专业版 内置mono版本:Mono/4.6.2.7 2.操作系统:centOs7 jexus独立版由于是免安装版并且内置mono,所 ...