写在前面

该博客思路源于在简书看到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. 深入理解C#

    简单认识.NET框架    (1)首先我们得知道 .NET框架具有两个主要组件:公共语言进行时CLR(Common Language Runtime)和框架类库FCL(Framework Class ...

  2. SQL Server-聚焦在视图和UDF中使用SCHEMABINDING(二十六)

    前言 上一节我们讨论了视图中的一些限制以及建议等,这节我们讲讲关于在UDF和视图中使用SCHEMABINDING的问题,简短的内容,深入的理解,Always to review the basics. ...

  3. JavaScript动画-拖拽改变元素大小

    ▓▓▓▓▓▓ 大致介绍 拖拽改变元素大小是在模拟拖拽上增加了一些功能 效果:拖拽改变元素大小 ▓▓▓▓▓▓ 拖拽改变元素大小原理 首先这个方块得知道我们想要改变这个它的大小,所以我给它设定一个范围,当 ...

  4. 走进缓存的世界(三) - Memcache

    系列文章 走进缓存的世界(一) - 开篇 走进缓存的世界(二) - 缓存设计 走进缓存的世界(三) - Memcache 简介 Memcache是一个高性能的分布式内存对象缓存系统,用于动态Web应用 ...

  5. C# salt+hash 加密

    一.先明确几个基本概念 1.伪随机数:pseudo-random number generators ,简称为:PRNGs,是计算机利用一定的算法来产生的.伪随机数并不是假随机 数,这里的" ...

  6. Java类变量和成员变量初始化过程

    一.类的初始化 对于类的初始化:类的初始化一般只初始化一次,类的初始化主要是初始化静态成员变量. 类的编译决定了类的初始化过程. 编译器生成的class文件主要对定义在源文件中的类进行了如下的更改: ...

  7. scanf类型不匹配造成死循环

        int i = 0; while (flag) { printf("please input a number >>> "); scanf("% ...

  8. iOS自定义model排序

    在开发过程中,可能需要按照model的某种属性排序. 1.自定义model @interface Person : NSObject @property (nonatomic,copy) NSStri ...

  9. BPM嵌入式流程解决方案分享

    一.需求分析由于企业业务的独特性或者企业高层独特的管理思想,很多客户选择了自行开发业务系统的方式来实现独有的竞争力. 这类信息系统通常经过了多年的开发,伴随着企业的发展一直在不断优化,与企业的业务非常 ...

  10. Android之使用Bundle进行IPC

    一.Bundle进行IPC介绍 四大组件中的三大组件(Activity.Service.Receiver)都是支持在Intent中传递Bundle数据的,由于Bundle实现了Parcelable接口 ...