Android面试一天一题(1Day)
写在前面
该博客思路源于在简书看到goeasyway博主写的Android面试一天一题系列,无copy之意,仅为让自己总结知识点,成长一点点。先感谢各位大神的无私分享~!
关于题目,大部分则出自AndroidInterview-Q-A和LearningNotes,当然既然是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)的更多相关文章
- 2021大厂Android面试高频100题最新汇总(附答案详解)
前言 现在越来越多的人应聘工作时都得先刷个几十百来道题,不刷题感觉都过不了面试. 无论是前后端.移动开发,好像都得刷题,这么多人通过刷题过了面试,说明刷题对于找工作还是有帮助的. 不过这其中有一个问题 ...
- android 面试准备基础题
1. 请描述下Activity的生命周期. 必调用的三个方法:onCreate() --> onStart() --> onResume(),用AAA表示 )父Activity启动子 ...
- Android面试优雅地介绍自己的项目
本文转载:m.blog.csdn.net/iamsamzhang/article/details/51916584 先说句题外话,很多公司16年秋招的内推已经开始啦,我目前知道的在北京有网易.百度和微 ...
- 2020年最新阿里、字节、腾讯、京东等一线大厂高频面试(Android岗)真题合集,面试轻松无压力
本文涵盖了阿里巴巴.腾讯.字节跳动.京东.华为等大厂的Android面试真题,不管你是要面试大厂还是普通的互联网公司,这些面试题对你肯定是有帮助的,毕竟大厂一定是行发展的标杆,很多公司的面试官同样会研 ...
- Android开发如何准备技术面试(含Android面试押题)
今年毋庸置疑是找工作的寒冬,每一个出来找工作的同学都是值得尊敬的.现在找工作,虽然略难,但是反过来看也会逼迫我们成为更加优秀的自己. 但是不管是旺季还是寒冬,有一些优秀的同学找工作还是挺顺利的.所以说 ...
- Android面试总结 (转)
1. 下列哪些语句关于内存回收的说明是正确的? (b) A. 程序员必须创建一个线程来释放内存 B. 内存回收程序负责释放无用内存 C. 内存回收程序允许程序员直接释放内存 D. 内存回收程序可以在指 ...
- 【Android面试】Android面试题集锦 (陆续更新)(最新2012-6-18) eoe上看到的
===============eoeAndroid社区推荐:======================= 1.Android开发新浪面试题[开发者必看哦]下载地址 http://www.eoeand ...
- Android面试题目及其答案
转自:http://blog.csdn.net/wwj_748/article/details/8868640 Android面试题目及其答案 1.Android dvm的进程和Linux的进程, 应 ...
- Android面试题目2
1. 请描述下Activity的声明周期. onCreate->onStart->onRemuse->onPause->onStop->onRestart->onD ...
随机推荐
- 0-1背包问题蛮力法求解(c++版本)
// 0.1背包求解.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> #define ...
- C# DateTime日期格式化
在C#中DateTime是一个包含日期.时间的类型,此类型通过ToString()转换为字符串时,可根据传入给Tostring()的参数转换为多种字符串格式. 目录 1. 分类 2. 制式类型 3. ...
- nodejs进阶(1)—输出hello world
下面将带领大家一步步学习nodejs,知道怎么使用nodejs搭建服务器,响应get/post请求,连接数据库等. 搭建服务器页面输出hello world var http = require ...
- netty5 HTTP协议栈浅析与实践
一.说在前面的话 前段时间,工作上需要做一个针对视频质量的统计分析系统,各端(PC端.移动端和 WEB端)将视频质量数据放在一个 HTTP 请求中上报到服务器,服务器对数据进行解析.分拣后从不同的 ...
- ASP.NET Core应用的错误处理[1]:三种呈现错误页面的方式
由于ASP.NET Core应用是一个同时处理多个请求的服务器应用,所以在处理某个请求过程中抛出的异常并不会导致整个应用的终止.出于安全方面的考量,为了避免敏感信息的外泄,客户端在默认的情况下并不会得 ...
- ASP.NET Core的路由[5]:内联路由约束的检验
当某个请求能够被成功路由的前提是它满足某个Route对象设置的路由规则,具体来说,当前请求的URL不仅需要满足路由模板体现的路径模式,请求还需要满足Route对象的所有约束.路由系统采用IRouteC ...
- python通过protobuf实现rpc
由于项目组现在用的rpc是基于google protobuf rpc协议实现的,所以花了点时间了解下protobuf rpc.rpc对于做分布式系统的人来说肯定不陌生,对于rpc不了解的童鞋可以自行g ...
- 简记用ArcGIS处理某项目需求中数据的步骤
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1. 背景 项目需求涉及如下几个步骤: a.矢量化 b.获取范围内要素 ...
- JavaScript实现DOM对象选择器
目的: 根据传入的选择器类型选出第一个符合的DOM对象. ①可以通过id获取DOM对象,例如 $("#adom"); ②可以通过tagName获取DOM对象,例如 $(" ...
- 【夯实Nginx基础】Nginx工作原理和优化、漏洞
本文地址 原文地址 本文提纲: 1. Nginx的模块与工作原理 2. Nginx的进程模型 3 . NginxFastCGI运行原理 3.1 什么是 FastCGI ...