1-ListView优化?ListView如何提高其效率?
1. Item布局,层级越少越好,使用hierarchyview工具查看优化。
2. 复用convertView ,使用历史的view
3. 自定义静态类ViewHolder,减少findViewById的次数
4. item中有图片时,异步加载
5. 快速滑动时,不加载图片
6. item中有图片时,应对图片进行适当压缩
7. 异步加载数据,分页加载数据
2-如何实现让ListView的条目显示不一样的布局?
1)重写BaseAdapter的getViewTypeCount()方法返回有几种条目类型
2)重写BaseAdapter的getItemViewType(int position)方法来实现
指定position的条目是什么类型的
3)在BaseAdapter的getView方法中根据当前position的条目类型去加载不同的View
3-ScrollView中嵌入ListView常见问题和解决方案?
问题:
ScrollView内部嵌套的ListView,数据显示不完整。
原因:
ScrollView的滑动事件的消费处理以及ListView控件的高度设定问题
解决方案:
第一种解决方案:手动动态设置ListView高度:
该方法缺陷:
1. Adapter中getView方法返回的View的必须由LinearLayout组成,如果使用其他的布局如RelativeLayout,在调用listItem.measure(0, 0);时就会抛异常
2. 把整个需要放在ScrollView中的内容,统统放在ListView中,原ListView上方的数据和下方数据,都作为现ListView的一个itemView,和原ListView中的单条数据是平级的关系。
一个单独的ListView就可以了
第二种解决方案:使用LinearLayout取代ListView
我们只需要自定义一个类继承自LinearLayout,为其加上对BaseAdapter的适配
第三种方案:自定义可适应ScrollView的ListView
自定义一个类继承自ListView,通过重写其onMeasure方法,达到对ScrollView适配的效果
三种方案的优缺点比较:
方案一:
优点:是不用对使用的控件做任何修改,只需要使用一个现成的方法就好了。
缺点:最大的限制是ListView的item只能由LinearLayout这一个布局组成,对于一些复杂的布局就不适用了
方案二:
优点:是完全解决了ScrollView嵌套ListView的问题,同时代码较少,你甚至可以直接使用LinearLayout,而在Activity中手动为LinearLayout添加子项控件,不过需要注意的是,在添加前需要调用其removeAllViews的方法,否则会抛出异常。
缺点:不能向ListView那样可以使用ViewHolder结构,在加载大量子项时会费很多时间在findViewById中。
方案三:
优点:是布局文件设计简单、Activity中的代码也很少。
跨平台开发相关面试题
4-简单描述一下Html5的特点?
本地存储特性(Class: OFFLINE & STORAGE)
基于HTML5开发的网页APP拥有更短的启动时间,更快的联网速度,这些全得益于HTML5 APP Cache,以及本地存储功能。Indexed DB(html5本地存储最重要的技术之一)和API说明文档。这也是WebView性能优化的一方面
设备兼容特性 (Class: DEVICE ACCESS)
从Geolocation(定位)功能的API文档公开以来,HTML5为网页应用开发者们提供了更多功能上的优化选择,带来了更多体验功能的优势。HTML5提供了前所未有的数据与应用接入开放接口。使外部应用可以直接与浏览器内部的数据直接相连,例如视频影音可直接与麦克风及摄像头相联。
连接特性(Class: CONNECTIVITY)
更有效的连接工作效率,使得基于页面的实时聊天,更快速的网页游戏体验,更优化的在线交流得到了实现。
HTML5拥有更有效的服务器推送技术,Server-Sent Event和WebSockets就是其中的两个特性,这两个特性能够帮助我们实现服务器将数据“推送”到客户端的功能。
网页多媒体特性(Class: MULTIMEDIA)
支持网页端的Audio、Video等多媒体功能, 与网站自带的APPS,摄像头,影音功能相得益彰。
三维、图形及特效特性(Class: 3D, Graphics & Effects)
基于SVG、Canvas、WebGL及CSS3的3D功能,用户会惊叹于在浏览器中,所呈现的惊人视觉效果。
性能与集成特性(Class: Performance & Integration)
没有用户会永远等待你的Loading——HTML5会通过XMLHttpRequest2等技术,帮助您的Web应用和网站在多样化的环境中更快速的工作。
CSS3特性(Class: CSS3)
在不牺牲性能和语义结构的前提下,CSS3中提供了更多的风格和更强的效果。此外,较之以前的Web排版,Web的开放字体格式(WOFF)也提供了更高的灵活性和控制性。
屏幕适配相关的面试题
5-屏幕适配的方式有哪些?
适配相关术语:
分辨率:eg:480*800,1280*720。表示物理屏幕区域内像素点的总和。(切记:跟屏幕适配没有任何关系)
因为我们既可以把1280*720的分辨率做到4.0的手机上面。我也可以把1280*720的分辨率做到5.0英寸的手机上面,如果分辨率相同,手机屏幕越小越清晰。
px(pix):像素,就是屏幕中最小的一个显示单元。不同设备显示效果相同。
dpi(像素密度):即每英寸屏幕所拥有的像素数,像素密度越大,显示画面细节就越丰富。
计算公式:像素密度=√{(长度像素数^2+宽度像素数^2)}/ 屏幕尺寸
注:屏幕尺寸单位为英寸 例:分辨率为1280*720 屏幕宽度为6英寸 计算所得像素密度约等于245,屏幕尺寸指屏幕对角线的长度。
dip: device independent pixels ,设备独立像素。不同设备有不同的显示效果,这个和设备硬件有关。
屏幕适配方式:
图片适配
在我们的Android工程目录中有如下drawable/mipmap-*dpi目录,这些目录是用来适配不同分辨率手机的。
不同的目录,代表手机不同的像素密度:
以下是Android系统的适配策略:
Android应用在查找图片资源时会根据其分辨率自动从不同的文件目录下查找。
如果在低分辨的文件目录中比如drawable-mdpi中没有图片资源,其他目录中都有,当我们将该应用部署到mdpi分辨率的手机上时,那么该应用会查找分辨率较高目录下的资源文件,
如果较高分辨率目录下也没有资源则只好找较低目录中的资源了。
尺寸适配
跟drawable目录类似的,在Android工程的res目录下有values目录,这个是默认的目录,同时为了适配不同尺寸手机我们可以创建一个values-1280x720的文件夹,同时将dimens.xml文件拷贝到该目录下。
在dimens.xml中定义一个尺寸,如下图所示。
在values-1280x720目录中的dimens.xml中定义同样的尺寸名称,但是使用不同的尺寸,如下图所示。
当我们在布局文件中使用长或者宽度单位时,比如下图所示,应该使用@dimen/width来灵活的定义宽度。
布局适配-(这种适配几乎不常见)
跟values一样,在Android工程目录中layout目录也支持类似values目录一样的适配,在layout中我们可以针对不同手机的分辨率制定不同的布局,如下图所示。
权重适配
在控件中使用属性android:layout_weight="1"可以起到适配效果,但是该属性的使用有如下规则:
只能用在线性控件中,比如LinearLayout。
竖直方向上使用权重的控件高度必须为0dp(Google官方的推荐用法)
水平方向上使用权重的控件宽度必须为0dp(Google官方的推荐用法)
代码适配
在java代码中动态计算控件的宽度和高度。
注意:计算的宽度和高度,这里涉及到dp和px之间的转化:
说明一下dp代表什么意思?
dip: device independent pixels ,设备独立像素。不同设备有不同的显示效果,这个和设备硬件有关。
指一个抽象意义上的像素,程序用它来定义界面元素。一个与密度无关,在逻辑尺寸上,与一个位于像素密度为160dpi的屏幕上的像素是一致的。
要把密度无关像素转换为屏幕像素,可以用这样一个简单的公式:pixels=dips*(density/160)。
举个例子,在DPI为240的屏幕上,1个DIP等于1.5个物理像素。
代码中相互换算:
百分比适配
该适配一般对图片进行适配的。
比如:在同一张图片,在不同的设备中,按照图片的宽高比例,进行缩放显示。
1. 获取图片的宽度和高度
2. 计算图片的宽度和高度的比例
3. 根据图片的比例,计算出图片的在设备中的显示的实际宽度和高度
6-请问平时开发过程中,你是如何做到多分辨率适配的?
1. 明确开发设备分辨率:一般选择1920 * 1080的分辨率。
2. .根据分辨率不同建立不同分辨率的资源图片
3. 在程序启动时,获取当前屏幕的分辨率和密度,在代码中进行适配
4. 根据目标设备,为不同分辨率的写不同的dimen文件。
5. 尽量使用权重适配
6. 根据需求可以使用代码适配以及百分比适配
7. 针对特殊的设备,进行特殊的适配
与设计模式相关的面试题
7-简单说说MVC,MVP原理以及它们之间的区别?并说明使用场景?
8-你一般在开发项目中都使用什么设计模式?如何来重构、优化你的代码?
从框架模式角度:
由之前的MVC模式 转型到 MVP模型
由于Android开发中,Activity并不是一个标准的MVC模式中的Controller,它的首要职责是加载应用的布局和初始化用户界面,并接受并处理来自用户的操作请求,进而作出响应。
随着界面及其逻辑的复杂度不断提升,Activity类的职责不断增加,以致变得庞大臃肿。当我们将其中复杂的逻辑处理移至另外的一个类(Presneter)中时,Activity其实就是MVP模式中View,它负责UI元素的初始化,建立UI元素与Presenter的关联(Listener之类),同时自己也会处理一些简单的逻辑(复杂的逻辑交由Presenter处理).
从设计模式角度:
工厂模式:主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。
比如:创建多个Fragment的过程,可以通过工厂模式,来实现。
观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新
单例模式:Android数据库操作比较讨厌多线程操作导致的数据错误,那么可以通过单例模式使得整个项目只能有一个SqliteDataBase对象,同时对增删改的操作做同步处理,可以保证整个项目同一时刻只有一个写操作,
代理模式:Android里的Service的bind模式,要求Service必须提供一个IBinder对象,Activity通过Ibinder对象的代理,可以调用Service里面的方法。
模板方法模式:定义一个操作中的算法的框架,而将具体的实现步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义算法的某些特定步骤。
比如:我们经常抽取的BaseActivity,BaseFragment就是对这种模式的使用
建造者模式:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。 [构建与表示分离,同构建不同表示]
也就是说:建造模式是将复杂的内部创建封装在内部,对于外部调用的人来说,只需要传入建造者和建造工具,对于内部是如何建造成成品的,调用者无需关心。
比如:android中AlertDialog的创建。一般在封装一个工具类时,我们使用这种模式
组合模式:将对象组合成树形结构以表示“部分到整体”的层次结构。这种模式使得用户对单个对象和组合对象的使用具有唯一性。
这种模式,开发中经常使用在组合控件中。
装饰者模式:动态地给一个对象添加一些额外的职责。
装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展
比如:listview添加一个能够添加头部视图headView的功能。这就是需要动态地添加一些额外的职责。而且为了解耦和不影响现有代码。
9-手写一个单例模式,能不能保证使用时对象的唯一性
首先单例模式大致分为五大类:
懒汉:需要加锁才能实现多线程同步,但是效率会降低。优点是延时加载。
恶汉:因为加载类的时候就创建实例,所以线程安全(多个ClassLoader存在时例外)。缺点是不能延时加载。
双重校验锁:在jdk1.5 之前Java内存模型中不一定管用。存在兼容的问题
静态内部类:延迟加载,减少内存开销。缺点:由于静态field在单例类加载时即进入到堆内存中,得不到回收
枚举:编写一个包含单个元素的枚举。不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象
与网络相关的面试题
10-Android与服务器交互的方式中的对称加密和非对称加密是什么(5分)
对称加密:
定义:加密和解密时使用相同的密钥(或是使用两个可以简单地相互推算的密钥)
加密算法:DES 和 AES – 数据加密算法
原理:
1. 客户端和服务端分别拥有一个相同的秘钥key
2. 客户端使用相同的秘钥key,对数据进行加密,发送给服务端
3. 服务器端接收到数据,使用相同秘钥key,进行解密。
非对称加密:
定义:加密和解密使用的是两个不同的密钥
加密算法:RAS-公钥加密算法
原理:
1. 客户端随机生成非对称加密密钥PK1,SK1
2. 客户端把PK1明文发送给服务端。
3. 服务端随机生成对称加密K,并用PK1加密后发送给客户端
4. 客户端拿到通过PK1加密后的K,通过SK1解密后,获取到服务端发来的对称加密密钥。
5. 双方完成对称加密密钥的交换,接下来就可以用 k 来进行数据加密传输。
缺点:缺乏身份认证机制,容易受到中间人攻击。
11-什么是cookie和session以及它们之间的区别(5分)
Cookie的认识:
是一种发送到客户浏览器的文本串,并保存在客户机硬盘上,可以用来在某个WEB站点会话间持久的保持数据。
ookie机制采用的是在客户端保持状态的方案
cookie的内容主要包括:名字(key),值(value),过期时间,路径和域。
其中名字和值:用于保存用户状态
路径与域:一起构成cookie的作用范围。
过期时间:
1. 若不设置过期时间,则表示这个cookie的生命期为浏览器会话期间,关闭浏览器窗口,cookie就消失
2. 若设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie仍然有效直到超过设定的过期时间
Session认识:
其实指访问者从进入网站到离开网站为止的那段时间。
session机制采用的是在服务器端保持状态的方案,服务器使用一种类似于map形式的数据结构,来保存信息
当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否已包含了一个session标识(称为session id):
如果已包含则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来
如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id
区别:
1、cookie数据存放在客户的浏览器上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
考虑到安全应当使用session。
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
考虑到减轻服务器性能方面,应当使用COOKIE。
4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
12-TCP/IP簇分为哪几层?TCP IP XMPP HTTP分别属于哪一层?(5分)
TCP/IP协议参考模型把整个ISO模型归类到四个抽象层中:
应用层:TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet,xmpp 等等
传输层:TCP,UDP
网络层:IP,ICMP,OSPF,EIGRP,IGMP
数据链路层:SLIP,CSLIP,PPP,MTU
TCP: 属于传输层协议
IP: 属于网络层协议
XMPP和Http都属于应用协议
13-说一下TCP协议中如何实现三次握手?
在TCP/IP协议中,TCP协议通过三次握手建立一个可靠的连接
第一次握手:客户端尝试连接服务器,向服务器发送syn包(同步序列编号Synchronize Sequence Numbers),客户端进入SYN_SEND状态等待服务器确认
第二次握手:服务器接收客户端syn包并确认(ack:确认字符,命令正确应答)),同时向客户端发送一个SYN+ACK的报文,此时服务器进入SYN_RECV接收状态
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包,此包发送完毕,客户端和服务器进入ESTABLISHED(已建立连接)状态,完成三次握手
14-UDP连接和TCP不同之处(5分)
TCP和UDP的相同点和不同点?
相同点:在传输消息对象时,会封装上ip信息,发送给服务器。
不同点:
TCP:
1. 传输大文件
2. 传输可靠(要经过三次握手确认)
3. 面向连接
4. 效率低
UDP:
1. 文件不得超过64k
2. 不可靠
3. 不面向连接
4. 效率高
15-保护用户登录账号的安全有哪些方法(5分)
1. 使用对称加密方式,对用户账号进行加密
2. 使用非对称加密方式,对用户进行加密
3. 使用https协议来代替http
4. 使用不可逆加密方式,对账号进行加密(比如 md5算法,sha1算法等)
16-http和https的区别(5分)
1. 定义
http: 超文本传输协议, 是一种规定了浏览器和万维网服务器之间互相通信的规则,通过因特网传送万维网文档的数据传送协议。
https: 由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,用来保证数据传输的安全性。端口为443。
Ssl: (Secure Socket Layer,安全套接字层),为网络通信提供安全及数据完整性的一种安全协议
2. 区别
l https协议需要到ca(证书管理机构。负责发放证书,确保证书申请者的身份和合法性等。)申请证书
l http是超文本传输协议,信息是明文传输,
l https 则是具有安全性的ssl加密传输协议
l http和https使用的是完全不同的连接方式用的端口也不一样,前者是80,后者是443
l http的连接很简单,是无状态的
l HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议 要比http协议安全HTTPS
17-说一下对Socket 理解或者TCP/IP的通讯原理?
1. 定义
socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信
2. 通信原理
socket是一种"打开—读/写—关闭"模式的实现,服务器和客户端各自维护一个"文件"。
在建立连接打开后,可以向自己文件写入内容供对方读取或者读取对方内容,通讯结束时关闭文件。
通讯步骤:
1. 服务器根据地址类型(ipv4,ipv6)、socket类型、创建socket
3. 服务器socket监听端口号请求,随时准备接收客户端发来的连接,这时候服务器的socket并没有被打开
5. 客户端打开socket,根据服务器ip地址和端口号试图连接服务器socket
6. 服务器socket接收到客户端socket请求,被动打开,开始接收客户端请求,直到客户端返回连接信息。这时候socket进入阻塞状态,所谓阻塞即accept()方法一直到客户端返回连接信息后才返回,开始接收下一个客户端谅解请求
9. 客户端向socket写入信息
10. 服务器读取信息
11. 客户端关闭
12. 服务器端关闭
与线程间通信机制相关面试题
18-简述handler消息机制的原理(10分)
Andriod提供了 Handler 和 Looper 来满足线程间的通信。
Handler 先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(Message Exchange)。
1) Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列)。
Looper工作原理:
1 Looper会不停地从消息队列中查看是否有新消息,如果有,处理消息,否则阻塞
2 Looper提供了一个getMainLooper方法,通过它可以在任何地方获取到主线程的Looper,也就是ActivityThread
3 Looper 提供了quit和quitSafely两个退出Looper方法,quit:会直接退出Looper。
quitSafely:只是设定了一个退出标记,然后把消息队列中的已有消息处理完毕后,才退出。
4 在子线程中创建Looper,需要调用Looper.getMainLooper,才能实现更新UI
5 在线程中通过手动创建Looper时,需要注意的是,所有的事情完成以后应该调用quit方法来终止消息循环,否则这个子线程会一直处于等待状态。
引发内存泄露
2)Handler: 你可以构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;或者接收Looper从Message Queue取出)所送来的消息。
3) Message Queue(消息队列):用来存放线程放入的消息。
MessageQueue工作原理:
1 MessageQueue主要包含两个操作:插入enqueueMessage和读取next
2 enqueueMessage作用:向消息队列中插入一条消息
3 next作用:从消息队列中取出一条消息并将其消息队列中移除
4 消息队列内部实现并不是真正的队列,而是一个单向链表的数据结构来维护的
5 消息的插入方式:1 按照发送的先后顺序插入队列中 2 按照发送延迟时间插入队列中
4)线程:main thread,而Android启动程序时会替它建立一个Message Queue。
19-子线程中能不能new Handler?(7分)
答:不能
如果在子线程中直接new Handler()会抛出异常java.lang.RuntimeException: Can't create handler inside thread that has not called
在没有调用Looper.prepare()的时候不能创建Handler,因为在创建Handler的源码中做了如下操作
Handler的构造方法中:
如果要在子线程中创建handler并且使用Handler,在创建Handler之前,创建对应的Looper
如下实现:
20-android线程间通信有哪些方法?
1. 全局变量
线程间内存共享,这是比较常用的通信方式和交互方式
注意:定义全局变量时最好使用volatile来定义,以防编译器对此变量进行优化
2. 线程级共享变量:ThreadLocal
ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。
提供三个核心方法:
、
get()方法是用来获取ThreadLocal在当前线程中保存的变量副本
set()用来设置当前线程中变量的副本
remove()用来移除当前线程中变量的副本
3. 共享文件和数据库
不同线程共享一份文件和数据库
4. Handler消息机制
使用Handler在子线程中处理任务,得到结果通过Handler消息机制,在主线程中处理结果
5. 线程同步
通过线程同步机制,可以使多个线程之间,同时对同一个内存地址进行写入和读取的操作。
21-多线程有几种实现方法?同步有几种实现方式?
线程实现方式主要有三种:
继承Thread类、
实现Runnable接口、
使用ExecutorService、Callable、FutureTask实现有返回结果的多线程。
注意:
其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的
同步实现方式:
1. 同步方法
即用synchronized关键字修饰的方法。
由于java的每个对象都有一个内置锁,当用此关键字修饰方法时,
内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。
2. 同步代码块
即有synchronized关键字修饰的语句块。
被该关键字修饰的语句块会自动被加上内置锁,从而实现同步
注:同步是一种高开销的操作,因此应该尽量减少同步的内容。
3. 使用特殊域变量(volatile)实现线程同步
a.volatile关键字为域变量的访问提供了一种免锁机制,
b.使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新,
c.因此每次使用该域就要重新计算
d.volatile不会提供任何原子操作,它也不能用来修饰final类型的变量
注:多线程中的非同步问题主要出现在对域的读写上,如果让域自身避免这个问题,则就不需要修改操作该域的方法。
用final域,有锁保护的域和volatile域可以避免非同步的问题
4. 使用重入锁实现线程同步
在JavaSE5.0中新增了一个java.util.concurrent包来支持同步。
ReentrantLock类是可重入、互斥、实现了Lock接口的锁。
它与使用synchronized方法和快具有相同的基本行为和语义,并且扩展了其功能
ReenreantLock类的常用方法有:
ReentrantLock() : 创建一个ReentrantLock实例
lock() : 获得锁
unlock() : 释放锁
5. 使用线程级变量实现线程同步
使用ThreadLocal管理变量,则每一个使用该变量的线程都获得该变量的副本,
副本之间相互独立,这样每一个线程都可以随意修改自己的变量副本,而不会对其他线程产生影响
ThreadLocal 类的常用方法
ThreadLocal() : 创建一个线程本地变量
get() : 返回此线程局部变量的当前线程副本中的值
initialValue() : 返回此线程局部变量的当前线程的"初始值"
set(T value) : 将此线程局部变量的当前线程副本中的值设置为value
22-简述synchronized和Lock的异同?
主要相同点:Lock能完成synchronized所实现的所有功能
主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放
23-简述一下你对线程池的理解 (10分)
为什么使用线程池?
由于并发的线程数量比较,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间,以及内存的开销。因此才引入线程池
线程池的作用:
提供了对线程的复用,减少重复创建线程的内存和CPU消耗
当线程池里没有可复用线程时会新建线程
当线程池里存在大量空闲线程时会回收线程,节约内存
线程池的实现原理:
1 如何线程池中线程数量未达到核心线程的数量,那么会直接开启一个核心线程来执行任务
2 如何线程池中的线程数量已经到达或者超过核心线程的数量,那么任务会被插入任务队列中排队等待执行
3 如何任务队列已满,这个时候,如果线程数量未到达线程池规定的最大值,那么会开启一个非核心线程来执行
线程池分类:
1:FixedThreadPool-线程数量固定的线程池。
特点:
当线程处于空闲状态时,它们并不会被回收,除非线程池被关闭。
当所有线程都处于活动状态时,新任务都会处于等待状态,直到有线程空闲出来
2:CachedThreadPool- 线程数量不定的线程池
特点:
它只有非核心线程,当线程池中的线程都处于活动状态时,线程池会创建新的线程来处理新任务,否则就会利用空闲的线程来处理新任务。
3:ScheduleThreadPool - 核心线程数量是固定的
特点:
核心线程固定,非核心线程没有限制,并且当非核心线程闲置时,被立即回收
4:SingleThreadExcutor - 线程池内部只有一个核心线程
特点:它确保所有的任务都在同一个线程中按顺序执行。
与延迟和异步任务相关试题
24-Android中有哪些方法实现定时和延时任务?它们的适用场景是什么?
答:
倒计时类
用CountDownTimer
实现:
延迟类
CountDownTimer,可巧妙的将countDownInterval设成和millisInFuture一样,这样就只会调用一次onTick和一次onFinish
TimerTask + Timer:虽然是定时器工具,但是它可以设置延迟时间,执行任务。
Thread.sleep:在此线程下,通过睡眠,延迟时间。
Handler.postDelay(runnable, delayTime): 通过Handler消息机制,延迟处理消息
定时类
TimerTask + Timer:是一种定时器工具,用来在一个后台线程计划执行指定任务。它可以计划执行一个任务一次或反复多次。
handler.sendMessageAtTime
AlarmManager,适用于定时比较长远的时间,例如闹铃
25-请介绍一下AsyncTask的内部实现,适用的场景?
AsyncTask是由线程池+工作线程 + Handler进行构建的一个异步任务工具类。
线程池:
为了在处理多个任务时,避免创建多个线程带来内存开销,内部维护了一个线程池,管理每个线程。
内部的线程池通过ThreadPoolExecutor来动态分配固定大小的核心工作线程。这样所有的异步任务都会放到线程池,
并维护每个工作线程。
工作线程:
该线程用于执行一个耗时的操作,内部通过FutrueTask接受一个WorkerRunnable接口,并在接口的call方法中,执行异步任务,此时调用AsyncTask类的
doInBackground()方法,做耗时操作。
由于FutrueTask类实现了FutrueRunnable接口,通过这个接口,在它的run方法中,执行任务。
可以方便的取消后台任务和获取后台任务的执行结果。
当获取后台结果之后。将结果交给handler了。
Handler消息机制更新UI:
当FutrueTask工作线程任务执行完成以后,把结果交给Handler,handler通过发送消息,在Main线程中接收消息,并调用
AsyncTask类的onPostExecute(Result result)方法,来处理结果
使用场景:
1. 大量任务并发执行时
2. 图片加载
3. 文件下载
4. 操作数据库
5. 网络请求