准备
一、Android 基础面试 https://www.jianshu.com/p/ffe7e0561c85?tdsourcetag=s_pcqq_aiomsg(还需要总结知识)
https://blog.csdn.net/songzi1228/article/details/99975018 (多线程的总结)
https://www.jianshu.com/p/90db19b4c98a (大佬的博客园来观看使用)
1.Activity异常的生命周期处理
@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
异常或者系统内存不足会调用该方法
2.Fragment的生命周期
Fragment的生命周期
3.SingleTask的启动模式
可以将不同的APP的activity中设置为相同的taskAffinity,虽然在两个应用当中但是他们会被分配到同一个Task中
4. View的事件分发机制
二、异步消息处理机制
1. 主线程中调用Loop,那么为什么没有造成阻塞呢?
ActivityThread的Main方法里面有个Loop的消息队列,ActivityThread 有个 getHandler 方法,得到这个 handler 就可以发送消息,然后 loop 里就分发消息,然后就发给 handler,
然后就执行到 H(Handler )里的对应代码。所以说ActivityThread的main方法主要就是做消息循环,一旦退出消息循环,那么你的程序也就可以退出了,所以这些代码就不会卡死。
2. AsyncTask
1). 组成:线程池+Handler
2). Sting : 指的是doInBackgroud的参数类型
String : 指的是onProgressUpdate的参数类型
Long : 指的是onPostExecute的方法的参数以及doInBackground的返回参数
public class AsynctaskText extends AsyncTask<String , String , Long>{
/**
* 运行在UI线程中,在调用doInBackground之前运行的,可以做一些控件初始化
*/
@Override
protected void onPreExecute() {
super.onPreExecute();
}
/**
*后台运行的方法,运行在非ui线程中,可以执行耗时操作
*/
@Override
protected Long doInBackground(String... strings) {
return null;
}
/**
*在doBackground里面会执行onProgressUpdate这个函数
*/
@Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}
/**
*运行在ui线程,在doInBackground之后去执行的,
*/
@Override
protected void onPostExecute(Long integer) {
super.onPostExecute(integer);
}
@Override
protected void onCancelled() {
super.onCancelled();
}
}
execute和executeOnExecutor的区别
execute : Execute方法是串行执行,需要一个一个去执行
executeOnExecutor : 并行执行,需要添加线程池参数, 任务可以同步进行
三、VIew绘制相关知识
1. window、surface、decorview
window : 是对我们Android系统当中窗口的一种抽象类,PhoneWindow是Window窗口的一个实现类。
DecorView : 是我们应用窗口的一个根容器(本质上是一个FreamLayout),主要包含两个参数TitleView 和 ContentView
surface : 是窗口独占一个surface的写实区域
3. ListView滑动时候为什么不会发生OOM的原因(RecycleBin的机制) : 将离开屏幕外的view删除并且存放到RecycleBin这个类里面,当准备展示下一个view的时候,它会从RecycleBin里面取出一个scrapView,然后就将它设置为converVIew的参数进行判断是否已经设置过,从getView里面有这个方法
从而到达view复用的作用
4.ListView的性能优化5个优化点:
1). converView
2).viewHolder
3).getVIew尽量少做耗时的操作(当滑动停止时候再去加载图片)
4).ListVIew中的item元素避免半透明
5).开启硬件加速
四、 异常与性能
1. 如何产生ANR
a). View的按键或者触摸事件在5秒没有得到回应
b). BroadcastReciver的onReceive()函数运行在了主线程中,在10秒内无法完成处理
c).Service的各个生命周期函数在20秒内无法完成处理
2. 如何解决ANR
a). 使用AsyncTask处理IO的耗时操作
b). 使用Thread或者HandlerThread提供异步操作
c). 使用Handler来处理工作线程的耗时操作
d). Activity里面的所有生命周期都是在主线程中,避免写大量的耗时操作
3. OOM容易混淆的概念
内存溢出:我们申请的内存已经超出虚拟机的最大内存的限度就会抛出Out Of memory
内存抖动 : 短时间大量的对象被创建然后就释放,触发的GC机制,严重占用内存区。
内存泄露 : 我们要回收的对象无法进行GC的回收操作
4. bitmap的讲解
(1).Bitmap的模型: Android 2.3.3之前,Bitmap的像素数据存放在Native内存,而Bitmap对象本身则存放在Dalvik Heap中。而在Android3.0之后,Bitmap的像素数据也被放在了Dalvik Heap中。
(2).在Android2.3.3之前推荐使用Bitmap.recycle()方法进行Bitmap的内存回收; 在Android3.0之后更注重对Bitmap的复用
(3). recycle 的方法: 它既回收JAVA的内存也回收native的内存,这个对象以后就不会再被调用了。当你没有对象时候就会有GC去回收它,建议不要主动去调用它(快速截屏)
(4).inBitmap参数的好处 : 前提是旧的inBitmap大小>=新的inBitmap的大小,否则不能复用。
(5). LRU的算法 : 内部使用LinkedHashMap作为缓存, get和put完成添加和获取的操作,HashMap的remove方法来移除对象,当内部缓存满的时候,会调用trimToSize把较早或者使用最少的缓存对象移除出去,添加新的对象。
(6). 三级缓存 : 网络->本地->内存
原理:第一次打开app时候,图片首先从网络获得,然后再本地和内存各缓存一份,再去请求相同的url的时候,就会去本地或者内存去找
(7). 图片产生OOM的原因
a.一个页面加载过多图片
b. 加载图片没有进行对图片尺寸、质量进行压缩
c.加载大量图片时候做图片缓存
(8) . 图片的种类
PNG : 无损压缩格式,支持透明通道
JPEG : 有损压缩格式,不支持透明通道
WEBP : 既支持有损压缩也支持无损压缩,也支持透明通道
GIF : 支持多帧动画
(9). 超大图片加载方案
可以使用BitMapRegionDecoder
5. UI卡顿的讲解
1). UI卡顿原因分析
(1).在UI线程中做轻微的耗时操作,导致UI卡顿
(2).布局Layout过于复杂,无法在16ms内完成渲染(从布局上),可以使用include、merage、view-stub这样标签作为处理,布局过于复杂使用自定义view
(3).同一时间动画执行次数太多,导致CPU或GPU负载过重
(4).View的过度绘制,导致某些像素在同一帧时间内过度绘制多次,从而让CPU或者GPU过重(从代码上) ----->自定义view使用clipRect来屏蔽被遮盖的view绘制
(5).冗余的资源或者逻辑导致加载过慢
(6).避免在onDraw里面执行对象的创建(这样会产生内存抖动)
(7).图片显示(监听ListView滑动时候,就不要加载图片,当监听到停止时候,再去加载图片)
6.常见内存泄露案例
1.单例:长生命周期的对象(Application的对象)持有短生命周期的对象(是指Activity的对象)---->解决getApplicationContext()
2. handler : 非静态内部类持有外部类的引用,导致于无法释放外部类的对象---->解决方法将handler至于为static的对象,然后将外部类改为弱引用来使用
3.线程引起: AsyncTask和Runnable使用匿名内部类,因为非静态内部类持有外部类的引用,和handler类似
4.文件的读写、数据库网络启用后没有关闭
5.注册广播没有关闭广播
7.内存管理
(1).分配机制
(2).回收机制
五大进程:前台进程、可见进程、服务进程、后台进程、空进程
(3).内存优化
当Service完成任务后,尽量停止它(可以使用IntentService)----->它是在异步线程中执行的,用完后它会自动释放对象的
避免滥用Bitmap导致内存的浪费
尽量少使用枚举常量,可以使用注解方法
使用多进程来分担主内存耗时
8.冷启动优化
五、开源框架的学习
1.AOP的切面编程(目前作为了解使用)
(1).注解使用先关介绍
@Before 前置通知,相当于BeforeAdvice
@AfterReturning 后置通知,相当于AfterReturningAdvice
@Around 环绕通知,相当于MethodInterceptor
@AfterThrowing抛出通知,相当于ThrowAdvice
@After 最终final通知,不管是否异常,该通知都会执行
@DeclareParents 引介通知,相当于IntroductionInterceptor (了解)
(2). JoinPoint 连接点对象可以获得参数讲解
目标对象:getTarget()
获得方法签名:getSignature()
获得方法名称:getSignature().getName()
获得实际参数:getArgs()
获得当前指定方法的类型:getKind()
案例1:性能监控
@Aspect
public class PerformanAop {
@Around("call(* com.example.mi.okhttp.MainActivity.**(..))")
public void getTime(ProceedingJoinPoint joinPoint){
Signature signature = joinPoint.getSignature();
String name = signature.toShortString();
long time = System.currentTimeMillis();
try {
joinPoint.proceed(); ----------------->执行该程序的方法
} catch (Throwable throwable) {
throwable.printStackTrace();
}
Log.d("ceshi", name + "=" + (System.currentTimeMillis() - time));
}
}
2.MVC的架构的介绍
C层 : 页面和数据交互,耦合程度高,不利于解耦
3.MVP的架构介绍
MVP的特点:
Presenter完全将Model和View解耦,主要逻辑处于Presenter中;Presenter和具体View没有直接关联,都是通过接口进行交互。
View变更时候,可以保持Presenter不变,所以Model和View已经完全解耦
MVP的优点:
低耦合:Model、VIew层的变换不回影响到对方
可重用性:Model层可用于多个View
方便测试:可以单独多Model和VIew层单独测试
MVP的缺点:
当有一个很大的复杂页面,这样接口机会新增加很多接口,导致维护成本很大。
解决方法:把一些通用的接口作为基类,其他接口去继承
4.MVC和MVP流程的大致区别
5.MVVM的数据模型
MVVM的特点:
ViewModel和Model/View进行双向绑定,View 发生改变时候,ViewModel会通知Model更新数据;Model数据更新时候,ViewModel会通知View更新显示
6.插件化模型(学习反射)主要解决
(1).动态加载 DexClassLoader、PathClassLoader学习(动态加载app)
(2).动态加载资源文件 AssetManager 动态加载资源文件
(3).代码的加载
7.热修复模型
(1).Android 类加载机制
PathClassLoader : 加载内存中已经安装的apk中的dex
DexClassLoader : 加载sd卡中的apk/jar
(2).热修复机制(通过向dexElements数组插入dex来完成热修复)
dexElements数组、ClassLoader会遍历dexElements这个数组
原理:dexElements数组会在基类的BaseClassLoader中创造好,DexClassLoader和PathClassLoade
都是继承BaseClassLoader这个类的,通过ClassLoader去遍历dexElements数组,加载这个数组
dex文件,如果BaseClassLoader加载到正确的dex文件后,就不会再去加载有crash的dex文件了,
把正确的dex文件排在dexElements数组前面即可。
8.进程保活的实现
(1).Android的进程优先级:前台优先级、可见进程、服务进程、后台进程、空进程(主要为了做缓存、缩短下次启动时间)
(2).进程保活方案
a.利用系统广播拉活
缺点:当只有在特定场景下才可以拉起保活,下次被杀死后,无法得到控制
b.利用系统Service机制拉活 : onStartCommand方法,返回START_STICKY
缺点:在短时间内被多次杀死就不会被拉活、被root或者其他工具被stop也是无法拉活的
c.通过native进程拉活(通过AMS的进程杀死)
d.进程相互唤醒(打开一个app同时唤醒另一个app)
e.提升Service进程优先级,比如改为前台进程 startForeground(1,notification)
f.JobScheduler用来检测你自己的服务是否被杀掉,如果被杀掉了,你重启自己的服务 缺点:需要有自启动权限
六、Java基础面试
1.synchronized(悲观锁)和lock的区别
synchronzied 同步代码块底层原理 : monitorenter指向同步代码块的开始位置,monitorexit指向同步代码块的结束位置
线程执行到monitorenter指令时,该线程对象持有锁,即线程获得monitor持有权,count计数器+1,获得线程锁
线程执行完毕后,执行monitorexit执行指令,count为0,释放锁。 注意:无论是正常结束还是异常结束,都会执行monitorexit指令
synchronized 的同步方法的底层原理 : ACC_SYNCHRONIZED的flag标记该方法是否是同步方法,从而执行相应的同步调用
2.sleep和wait(notify)区别
sleep是Thread的内部的一个静态方法,可以再任何地方调用;wait是Object成员方法,只能在synchroized代码中被调用,其他地方调用会非法监控异常
在等待时候,wait是释放锁的,用于线程交互;sleep会一直持有锁,不会改变锁的状态,用于线程切换cpu的状态
3.lock、synchronized 和 volatile的区别
synchronized 和 volatile 的区别
volatile只能在线程内存和主内存之间存一个变量值,synchronized可以修饰类、对象、方法等,但是synchronized很消耗内存
volatile的理解:具有可见性、有序性,不具备原子性、禁止指令重排。 volatile修饰的变量会强制把数值写入主内存中
synchronized 和 lock 的区别
synchronized是Java的关键字,Lock是接口
synchronized是自动释放锁,Lock需要手动释放锁,所以写到try catch中并且在finally中释放锁
synchronized无法中断等待的锁,Lock可以中断,它可以在激烈的读写操作
4.线程池工作流程:
(1).首先判断线程池是否已经满了
(2).其次是判断工作队列是否已经满了
(3).最后判断整个线程池是否满了
五种线程池、四种拒绝策略、三种阻塞队列
五种线程池
threadPool = Executors.newCachedThreadPool(); //有缓冲的线程池,线程数 JVM 控制
threadPool = Executors.newFixedThreadPool(3); //固定大小的线程池,支持线程池并发
threadPool = Executors.newScheduledThreadPool(2); //固定大小的线程池,支持定时或者周期执行任务
threadPool = Executors.newSingleThreadExecutor(); //单线程的线程池,只有一个线程在工作
threadPool = new ThreadPoolExecutor(); //默认线程池,可控制参数比较多
四种拒绝策略
rejected = new ThreadPoolExecutor.AbortPolicy(); //默认,队列满了丢任务抛出异常
rejected = new ThreadPoolExecutor.DiscardPolicy(); //队列满了丢任务不异常
rejected = new ThreadPoolExecutor.DiscardOldestPolicy(); //将最早进入队列的任务删,之后再尝试加入队列
rejected = new ThreadPoolExecutor.CallerRunsPolicy(); //如果添加到线程池失败,那么主线程会自己去执行该任务
三种阻塞队列
有限队列
ArrayBlockingQueue<>(5); //基于数组的先进先出队列,有界
SynchronousQueue<>(); //无缓冲的等待队列,无界 适用于newCachedThreadPool线程池
无限队列
LinkedBlockingQueue<>(); //基于链表的先进先出队列,无界 适用于newFixedThreadPool、newScheduledThreadPool
参数讲解:
* corePoolSize:核心线程池大小
* maximumPoolSize:最多线程池大小
* keepAliveTime:表示空闲线程的存活时间
* unit:keepAliveTime时间单位
* workQueue:阻塞任务队列
* threadFactory:新建线程工厂
* RejectedExecutionHandler:保护策略
5.throw和throws的区别
throw : 用在方法体内,跟的是对象名,throw抛出异常,一定会抛出某种异常
throws : 用在方法后面,跟的是类名,它抛出的异常只是一种可能性,并不一定会抛出异常的
6.final、finalize、finally的关键字的区别
final : 修饰符,可以修饰类,不能再派生新的子类也不能作为父类被继承 ; 可以修饰变量,该变量的数值就不能修改
finally : try ... catch 语句中使用
finalize : 在垃圾回收时候使用,被清理对象没有被引用的情况下调用的。
7.注解相关介绍
1.Retention : 定义注解保留的时间
RetentionPolicy.SOURCE 注解只保留在源码,在编译器进行编译时会被忽略
RetentionPolicy.CLASS 注解由编译器保存在class文件中,但不需要在运行时由VM保留,无法通过反射读取,这是默认的策略。
RetentionPolicy.RUNTIME 注解由编译器保存在class文件中,并在运行时由VM保留,可以通过反射读取。
2.Target : 修饰对象的范围
ElementType.TYPE:允许被修饰的注解作用在类、接口和枚举上
ElementType.FIELD:允许作用在属性字段上
ElementType.METHOD:允许作用在方法上
ElementType.PARAMETER:允许作用在方法参数上
ElementType.CONSTRUCTOR:允许作用在构造器上
ElementType.LOCAL_VARIABLE:允许作用在本地局部变量上
ElementType.ANNOTATION_TYPE:允许作用在注解上
ElementType.PACKAGE:允许作用在包上
8.触发GC的条件
(1). 当应用程序空闲时,即没有应用线程再运行时,GC会被调用的
(2). JAVA内存不足的时候,GC会被调用
9. 减少GC的开销措施
(1). 不要显示调用System.gc()
(2).尽量减少创建临时对象(相当于减少垃圾的产生,从而延长第二次GC的触发时间),对象不用时候最好显示设置为null(有利于GC收集器判定垃圾,从而提高垃圾回收)
(3). 尽量使用StringBuffer,而不用String来增加字符串
(4). 能使用基本变量就不用封装好的对象(比如int ---> Integer对象)
(5). 尽量减少使用静态变量(静态变量属于全变量,不会被GC回收掉,他们也会一直占用内存,增加GC的次数)
10.终止线程的方法
1.while(boolean 变量值去终止) ------> 但是不会被立即终止线程
2.while(!Thread.interrupted())---------->判断是否执行Thread.interrupted这个方法,执行之后一定在try..catch..中的catch方法中执行return,这样才可以真正中断该方法
3. while(flag && ! Thread.interrupted()) ----->这两个方法去真正执行中断程序
private volatile boolean flag = false
11.多线程优化
将非UI线程设置线程等级,一般下载线程Thread.setThreadPriority(Processs.THREAD_PRIORITY_BACKGROUND);
七、网络相关的知识
1.http和https的区别
HTTPS协议需要到CA申请证书,一般免费证书很少,需要交费。
HTTP协议运行在TCP之上,所有传输的内容都是明文,HTTPS运行在SSL/TLS之上,SSL/TLS运行在TCP之上,所有传输的内容都经过加密的。
HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
HTTPS可以有效的防止运营商劫持,解决了防劫持的一个大问题。
2. http1.0、http1.1和http2.0区别
http1.0 1.0+ : 支持版本号、请求头、代理连接
http1.1 : 默认持久连接、支持缓存、支持管道方法发送多个请求 (一个TCP只能连接一个HTTP,不能复用;只能单向请求方式)
http2.0 : 支持多路复用,可以设定请求的优先级;支持双向通信;去除不需要的HTTP请求头,减少网络带宽
3.Http的请求方式
常见以下四种:
get : 获取资源
post : 创建资源
put : 更新资源
delete : 删除资源
4.get和post的区别
url可见性 : get的url可见(不安全) post的url参数不可见(安全)
数据传输上 : get通过拼接url进行传递参数 post通过body体传输参数
缓存性: get请求是可以缓存的 post请求不可以缓存
后退页面的反应 : get请求页面后退时,不产生影响 post请求页面后退时,会重新提交请求
传输数据的大小 : get一般传输数据大小不超过2k-4k post请求传输数据的大小可以自己,也可以无限大
5. cookie和session的区别
存放位置不同:cookie存放在客户端,session存放在服务端的
存取方式不同 : cookie用键值对,session可以保存任何内容
安全性 : cookie保存在客户端,所以安全性比session低
有限期不同 : cookie可以设置时间,session则不能
set-cookie:[expires过期、到期)=new.Date(Date.now() +10 *1000)] 10S后过期,如果不设置默认是关闭浏览器立即失效
对服务器压力不同 : 处于高并发情况下,cookie比session要高,因为它是保存在客户端的
6.输入URL后HTTP请求返回完整的过程
7.网络模式
8.三次握手的过程
SYN(synchronous建立联机) ACK(acknowledgement 确认) Sequence number(顺序号码)
第一次握手:主机A发送位码为syn=1,随机产生seq number=1234567的数据包到服务器,主机B由SYN=1知道,A要求建立联机;
第二次握手:主机B收到请求后要确认联机信息,向A发送ack number=(主机A的seq+1),syn=1,ack=1,随机产生seq=7654321的包;
第三次握手:主机A收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ack是否为1,若正确,主机A会再发送ack number=(主机B的seq+1),ack=1,主机B收到后确认seq值与ack=1则连接建立成功。
4.四次挥手
FIN (希望断开连接) ACK(acknowledgement 确认) Sequence number(顺序号码)
5.三次握手和四次挥手的面试点
为什么不能用两次握手进行连接
三次握手是为了确保双方都已经进入准备好的状态,可以进行通信,而两次握手的创建可能造成死锁
假如:当C给S发一个连接请求,然后把C一个应答,这时候S已经认为创建成功了,但是C认为还没有创建成功,将忽略S那边发来的数据,还在等待应答中,S发出的分组超时后,
再次发送请求,这样就会形成死锁
如果已经建立了连接,但是客户端突然出现故障了怎么办?
TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,
时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,
服务器就认为客户端出了故障,接着就关闭连接。
6.TCP和UDP的区别
a.基于连接与无连接;
b.对系统资源的要求(TCP较多,UDP少);
c.UDP程序结构较简单;
d.流模式与数据报模式 ;
e.TCP保证数据正确性,UDP容易丢包;TCP保护数据的顺序,UDP不行 UDP应用于IP电话和实时视频会议
7.Http请求协议的讲解
8.请求头的常见属性详解
User-Agent : 向服务器请求的操作系统以及版本号等
Referer : 你当前网页的上一个地址
Cache-Control : 缓存
Connection : 连接的类型(长连接)
Range : 多线程取舍时候,截取某一个字段
If-Match :
If-Modified-Since :
If-None-Match :
9.响应头的讲解
Cache-Control : 缓存
Content-Encoding : gzip 编码格式: 压缩
Content-Type : text/html 直接的文本、html类型
响应码 : 100-199 信息提示
200-299 成功
300-399 重定向
400-499 客户端错误
500-599 服务端错误
八、自定义注解的学习
@Retention:注解的保留位置
@Retention(RetentionPolicy.SOURCE) //注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.CLASS) // 默认的保留策略,注解会在class字节码文件中存在,但运行时或者反射都无法获得,
@Retention(RetentionPolicy.RUNTIME) // 注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Target:注解的作用目标
@Target(ElementType.TYPE) //接口、类、枚举、注解
@Target(ElementType.FIELD) //字段、枚举的常量
@Target(ElementType.METHOD) //方法
@Target(ElementType.PARAMETER) //方法参数
@Target(ElementType.CONSTRUCTOR) //构造函数
@Target(ElementType.LOCAL_VARIABLE)//局部变量
@Target(ElementType.ANNOTATION_TYPE)//注解
@Target(ElementType.PACKAGE) ///包
@Document:说明该注解将被包含在javadoc中
@Inherited:说明子类可以继承父类中的该注解
案例:
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface Xml {
String[] layouts();
}
@Xml(layouts = "activity_main")
------------------------回家需要再调试看看---------------------------------
2.Activity之间的通信
Intent/Bundle
3.Activity向Fragment传递数据
1).Bundle之间通信
fragment.setArguments------>Activity与Fragment之间的通信桥梁
getArguments()---->获得Bundle对象,还是key-value的模式
2).直接在Activity之间定义
在onAttach绑定时候,强制转换Acitivity的对象获得真实对象
4.Fragment向Activity对象传递数据
调用流程:
5.Activity与Service之间通信
1).绑定服务,利用ServiceConnection之间的通信
Activity写的代码:
Service写的代码:
2).利用Intent之间的通信
3).定义一个callback接口来监听服务中进程的变化
Service定义接口
Activity进行数据的调用
7.service和IntentService的区别
onHandleIntent在IntentService是抽象类,需要继承去实现的
相比与Service它使用好处是不用你去手动释放,当你执行完onHandleIntent就会释放service,
其次就是他可以通过执行HandlerThread执行异步操作
8.service的启动和绑定的讲解
service的绑定:
启动服务比绑定服务的优先级高
先绑定服务后启动服务: 绑定服务会转为启动服务运行状态,如果绑定的activity销毁,服务会继续运行
先启动服务后绑定服务: 服务不会转为绑定服务状态,会和Activity绑定,但是activity销毁,会按启动服务生命周期走
startService : 让服务长期运行在后台,但是无法与服务进行通讯
bindServcie : 可以与服务进行通讯,但是无法长期运行在后台
9.parcelable和serializable区别学习
组件之间存储数据一般用parcelable,serializable将对象写到磁盘中
序列化: 内存中的对象----->磁盘
反序列化: 磁盘中的对象---->内存
parcelable的实现步骤:
1)implements Parcelable
2)重写writeToParcel方法,将你的对象序列化为一个Parcel对象,即:将类的数据写入外部提供的Parcel中,打包需要传递的数据到Parcel容器保存,以便从 Parcel容器获取数据
3)重写describeContents方法,内容接口描述,默认返回0就可以
4)实例化静态内部对象CREATOR实现接口Parcelable.Creator
public class MyParcelable implements Parcelable
{
private int mData;
public int describeContents()
{
return 0;
}
public void writeToParcel(Parcel out, int flags)
{
out.writeInt(mData);
}
public static final Parcelable.Creator<MyParcelable> CREATOR = new Parcelable.Creator<MyParcelable>()
{
public MyParcelable createFromParcel(Parcel in)
{
return new MyParcelable(in);
}
public MyParcelable[] newArray(int size)
{
return new MyParcelable[size];
}
};
private MyParcelable(Parcel in)
{
mData = in.readInt();
}
}
简而言之: 通过writeToParcel将你的对象映射成Parcel对象,再通过createFromParcel将Parcel对象映射成你的对象
10.AIDL的使用
11.WebView面试讲解
1).webview在布局文件中的使用: webview写在其他容器中时(webview完全销毁的办法,否则会内存泄漏)
2).webviewClient.onPageFinished-------->WebChromeClent.onProgressChanged() : 页面跳转时候调用这个函数
posted on 2019-09-15 20:28 zhang11111wei 阅读(353) 评论(0) 编辑 收藏 举报