一、Android部分
1.各个版本新特性
Android 10.x
- 5G
Android 9.x
- ”刘海“屏幕支持
- 多摄像头支持,可以同时获取多个视频流
- 通知
- 增强体验
- 通道设置、广播以及免打扰
Android 8.x
- 画中画,支持将电影屏幕缩小成悬浮窗口
- 安装APK权限
Android 7.x
- 通知栏快捷回复
- 引入全新的JIT编译器,使得APP安装速度快了75%
- 夜间模式
Android 6.x
- 动态权限管理
- 指纹识别
- 取消支持Apache HTTP客户端
2.Android中的几种动画
帧动画:指通过指定每一帧的图片和播放时间,有序的进行播放而形成动画效果,比如想听的律动条。
补间动画:指通过指定View的初始状态、变化时间、方式,通过一系列的算法去进行图形变换,从而形成动画效果,主要有Alpha、Scale、Translate、Rotate四种效果。注意:只是在视图层实现了动画效果,并没有真正改变View的属性,比如滑动列表,改变标题栏的透明度。
属性动画:在Android3.0的时候才支持,通过不断的改变View的属性,不断的重绘而形成动画效果。相比于视图动画,View的属性是真正改变了。比如view的旋转,放大,缩小oid中的几种动画
3.Handler原理
有3个关键类,Handler,Looper,MessageQueue
Handler封装了消息的发送,主要包括消息发送给谁
Lopper 轮训器
内部包含一个消息队列也就是MessageQueue,所有的Handler发送的消息都走向这个消息队列
Looper.Lopper()方法,就是一个死循环,不断的从MessageQueue取消息,如有消息就处理消息,没有消息就阻塞
MessageQueue,是一个消息队列,链表的结构,先进先出的原则,可以添加消息并处理消息
Handler也很简单,内部会跟Looper进行关联,也就是说在Handler的内部可以找到Looper,找到了Looper也就找到了MessageQueue,在Handler中发送消息,其实就是向MessageQueue队列中发送消息
handler负责发送消息,Looper负责接收Handler发送的消息,并直接把消息回传给handler自己
4.Service启动方式
startService和bindService
5.事件分发机制
Android事件分发机制遵从 Activity 到 ViewGroup 到 View 的顺序进行事件分发
事件分发过程由3个方法协作完成
第一个方法 dispatchTouchEvent
用于分发事件。调用时刻是当点击事件能够传递给当前View时,该方法就会被调用
第二个方法 onInterceptTouchEvent
用于拦截事件。只存在于ViewGroup,普通的View无该方法。调用时刻是在ViewGroup的dispatchTouchEvent()内部调用
第三个方法 onTouchEvent
用于处理事件。调用时刻是在dispatchTouchEvent内部调用
6.Activity启动模式
有4种:standard,singleTop,singleTask,singleInstance
standard模式
默认启动模式,每次激活Activity都会创建Activity实例,并放入任务栈中
使用场景:大多数Activity
singleTop模式
当前的 Acitivity 如果存在任务栈顶,则不需要创建新的activity,否则就会创建新的实例并放入栈顶,即使栈中已经存在Activity实例,只要不在栈顶,都会创建实例
使用场景:新闻类或者阅读类APP的内容页面
singleTask模式
当前的Acitivity如果存在任务栈中,则不需要创建新的activity实例,并把这个activity之上的实例,通通出栈
使用场景:浏览器主界面,不管从多少个应用启动浏览器,只会启动主界面一次,都会走onNewIntent,并且会清空主界面上面的其它页面。
singleInstance模式
当前的Acitivity如果存在该应用中的任何一个任务栈中,则不需要创建新的activity
使用场景:闹钟提醒,将闹钟提醒与闹钟设置分离。
7.Activity启动过程
整个应用程序的启动过程要执行很多步骤,但是整体来看,主要分为以下五个阶段:
1)Launcher通过Binder进程间通信机制通知ActivityManagerService,它要启动一个Activity;
2)ActivityManagerService通过Binder进程间通信机制通知Launcher进入Paused状态;
3)Launcher通过Binder进程间通信机制通知ActivityManagerService,它已经准备就绪进入Paused状态,于是ActivityManagerService就创建一个新的进程,用来启动一个ActivityThread实例,即将要启动的Activity就是在这个ActivityThread实例中运行;
4)ActivityThread通过Binder进程间通信机制将一个ApplicationThread类型的Binder对象传递给ActivityManagerService,以便以后ActivityManagerService能够通过这个Binder对象和它进行通信;
5ActivityManagerService通过Binder进程间通信机制通知ActivityThread,现在一切准备就绪,它可以真正执行Activity的启动操作了
8.Binder机制相关
简单说一下你对Android的Binder机制的理解?
在Android启动的时候,Zygote进程孵化出第一个子进程叫SystemServer,而在这个进程中,很多系统提供的服务,比如ActivityManagerSerivce, PowerManagerService等,都在此进程中的某一条线程上运行。
而很多用户开发的应用程序,基于安全的考虑,在安装到系统中的时候,都会被分配一个独特的UID,运行在一个单独的进程中。
基于Linux的用户安全机制,它们是没有办法直接访问到上述系统服务的。
但是在实际中,App很多时候是需要跟这些系统服务进行通信的,也就是要进行进程间通信。
而Binder机制则是Android系统实现进程间通信(IPC)的机制之一
9.IntentService
1.它本质是一种特殊的Service,继承自Service并且本身就是一个抽象类
2.它可以用于在后台执行耗时的异步任务,当任务完成后会自动停止
3.它拥有较高的优先级,不易被系统杀死(继承自Service的缘故),因此比较适合执行一些高优先级的异步任务
它内部通过HandlerThread和Handler实现异步操作
4.创建IntentService时,只需实现onHandleIntent和构造方法,onHandleIntent为异步方法,可以执行耗时操作
5.即使我们多次启动IntentService,但IntentService的实例只有一个,这跟传统的Service是一样的,最终IntentService会去调用onHandleIntent执行异步任务。
6.当任务完成后,IntentService会自动停止,而不需要手动调用stopSelf()。另外,可以多次启动IntentService,每个耗时操作都会以工作队列的方式在IntentService中onHandlerIntent()回调方法中执行,并且每次只会执行一个工作线程
10.热修复的原理
我们知道Java虚拟机 —— JVM 是加载类的class文件的,而Android虚拟机——Dalvik/ART VM 是加载类的dex文件,而他们加载类的时候都需要ClassLoader,ClassLoader有一个子类BaseDexClassLoader,而BaseDexClassLoader下有一个数组——DexPathList,是用来存放dex文件,当BaseDexClassLoader通过调用findClass方法时,实际上就是遍历数组,找到相应的dex文件,找到,则直接将它return。而热修复的解决方法就是将新的dex添加到该集合中,并且是在旧的dex的前面,所以就会优先被取出来并且return返回
11.页面卡顿的原因
(1)过于复杂的布局
(2)UI线程的复杂运算
(3) 频繁的GC,导致频繁GC有两个原因:1、内存抖动, 即大量的对象被创建又在短时间内马上被释放.2、瞬间产生大量的对象会严重占用内存区域。
12.Activity生命周期
13.Activity的生命周期
onCreate() -> onStart() -> onResume() -> onPause() -> onStop() -> onDetroy()
A页面跳B页面,然后finish B 页面,A页面的生命周期是:
onPaused,onStop,onRestart,onResume
处于A页面按home键 A页面生命周期:onPaused,onStop
横竖屏切换时Activity的生命周期变化?
[图片上传失败...(image-a3b553-1609228574306)]
1.如果没有配置android:ConfigChanges,这时默认让系统处理,就会重建Activity,此时Activity的生命周期会走一遍。
onSaveInstanceState() 和onRestoreIntanceState()
资源相关的系统配置发生改变或者资源不足:例如屏幕旋转,当前Activity会销毁,并且在onStop之前回调onSaveInstanceState保存数据,在重新创建Activity的时候在onStart之后回调onRestoreInstanceState。其中Bundle数据会传到onCreate(不一定有数据)和onRestoreInstanceState(一定有数据)。
用户或者程序员主动去销毁一个Activity的时候不会回调,其他情况都会调用,来保存界面信息。如代码中finish()或用户按下back,不会回调。
\2. 如果配置 android:configChanges="orientation|keyboardHidden|screenSize">,此时Activity的生命周期不会重走一遍,Activity不会重建,只会回调onConfigurationChanged方法。
13.Service生命周期?
service 启动方式有两种startService()
和bindService()
不同的启动方式他们的生命周期是不一样
startService()
生命周期:startService() --> onCreate()--> onStartCommand()--> onDestroy()
这种方式启动的话,注意以下几个问题:
第一:当我们通过startService被调用以后,多次再调用startService(),onCreate()方法也只会被调用一次,而onStartConmon()会被多次调用当我们调用stopService()的时候,onDestroy()就会被调用,从而销毁服务
第二:当我们通过startService启动时候,通过intent传值,在onStartCommand()方法中获取值的时候,一定要先判断intent是否为null
bindService()
生命周期走法:bindService()-->onCreate()-->onBind()-->unBind()-->onDestroy()
bingservice 这种方式进行启动service好处是更加便利activity中操作service,比如加入service中有几个方法,a,b ,如果要在activity中调用,在需要在activity获取ServiceConnection对象,通过ServiceConnection来获取service中内部类的类对象,然后通过这个类对象就可以调用类中的方法,当然这个类需要继承Binder对象
14.Broadcast注册方式与区别
注册方式主要有两种
第一种是静态注册(常驻型广播),需要在清单文件中进行注册,这种方式注册的广播,不受页面生命周期的影响,即使退出了页面,也可以收到广播。这种广播一般用于像开机自启动等,由于这种注册的方式的广播是常驻型广播,所以会占用CPU的资源。
第二种是动态注册(非常驻型广播),需要在代码中注册的,受到生命周期的影响,退出页面后,就不会收到广播,我们通常运用在更新UI方面。这种注册方式优先级较高。最后需要解绑,否会会内存泄露。
15.View的绘制流程
View的绘制流程:OnMeasure()——>OnLayout()——>OnDraw()
第一步:OnMeasure():测量视图大小
从顶层父View到子View递归调用measure方法,measure方法又回调OnMeasure。
第二步:OnLayout():确定View位置,进行页面布局
从顶层父View向子View的递归调用view.layout方法的过程,即父View根据上一步measure子View所得到的布局大小和布局参数,将子View放在合适的位置上。
第三步:OnDraw():绘制视图
ViewRoot创建一个Canvas对象,然后调用OnDraw()。
六个步骤:
①、绘制视图的背景;
②、保存画布的图层(Layer);
③、绘制View的内容;
④、绘制View子视图,如果没有就不用;
⑤、还原图层(Layer);
⑥、绘制滚动条。
16.保存Activity状态
onSaveInstanceState(Bundle)会在activity转入后台状态之前被调用,也就是onStop()方法之前,onPause方法之后被调用
OnPause()->onSaveInstanceState()->onStop();
17.Android中跨进程通讯的几种方式
有四种方式:intent,contentProvider,广播,AIDL服务
intent:访问其它程序的Activity,它需要传递一个uri,,比如说打电话。
contentProvider:使用数据共享的形式,例如访问系统相册
广播:例如显示系统时间
AIDL服务
RecyclerView和ListView的区别
RecyclerView可以完成ListView,GridView的效果,还可以完成瀑布流的效果。同时还可以设置列表的滚动方向(垂直或者水平);
RecyclerView中view的复用不需要开发者自己写代码,系统已经帮封装完成了。RecyclerView可以进行局部刷新。RecyclerView提供了API来实现item的动画效果。
在性能上:如果需要频繁的刷新数据,需要添加动画,则RecyclerView有较大的优势。如果只是作为列表展示,则两者区别并不是很大
列出几种常见的解决消息即时获取方案
1.轮询(Pull)方式:客户端定时向服务器发送询问消息,一旦服务器有变化则立即同步消息。
2.SMS(短信消息)(Push)方式:通过拦截SMS消息并且解析消息内容来了解服务器的命令,但这种方式一般用户在经济上很难承受
3.持久连接(Push)方式:客户端和服务器之间建立长久连接,这样就可以实现消息的及时性和实时性。
APP优化
APP启动优化
App启动的方式有三种:
冷启动:App没有启动过或App进程被killed, 系统中不存在该App进程, 此时启动App即为冷启动。
热启动:热启动意味着你的App进程只是处于后台, 系统只是将其从后台带到前台, 展示给用户。
介于冷启动和热启动之间, 一般来说在以下两种情况下发生:
(1) 用户按back键退出了App, 然后又启动了App,进程可能还在运行, 但是activity需要重建。
(2) 用户退出App后, 系统可能由于内存原因将App杀死, 进程和activity都需要重启, 但是可以在onCreate中将被动杀死所保存的状态(saved instance state)恢复。
优化方法:
Application的onCreate(特别是第三方SDK初始化)或首屏Activity的渲染都不要进行耗时操作,如果有,就可以放到子线程或者IntentService中
布局优化
相应优化
内存优化
电池使用优化
网络优化
网络连接对用户的影响:流量,电量,用户等待
可在Android Studio下方logcat旁边那个工具Network Monitor检测
*1.API设计*:App与Server之间的API设计要考虑网络请求的频次, 资源的状态等. 以便App可以以较少的请求来完成业务需求和界面的展示
*2.Gzip压缩:*使用Gzip来压缩request和response, 减少传输数据量, 从而减少流量消耗
*3.图片的Size:*可以在获取图片时告知服务器需要的图片的宽高, 以便服务器给出合适的图片, 避免浪费.
*4.网络缓存:*适当的缓存, 既可以让我们的应用看起来更快, 也能避免一些不必要的流量消耗
Android内存泄漏及管理
内存溢出(OOM)和内存泄露(对象无法被回收)的区别?
*内存溢出* out of memory:是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。内存溢出通俗的讲就是内存不够用
*内存泄露* memory leak:是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光
Android内存泄漏的原因
第一点,使用ListView时造成的内存泄漏
解决方法,使用ConvertView进行缓存
第二点,使用集合容器时造成的内存泄漏
解决方法,在退出程序之前,将即合里的东西clear,然后置为null,再退出程序
第三点,使用WebView时造成内存泄漏
解决方法,当我们不使用WebView对象时,应该调用destory方法来销毁它,释放占用的内存,否则长期占用的内存也不能被回收,从而造成内存泄漏
第四点,资源未关闭造成内存泄漏
使用了BroadcastReceiver、ContentObserver、File、Cursor、Stream、Bitmap等资源造时造成内存泄漏
如何保证Service不被杀死?
一、提供进程优先级,降低进程被杀死的概率
方法一:监控手机锁屏解锁事件,在屏幕锁屏时启动1个像素的 Activity,在用户解锁时将 Activity 销毁掉。
方法二:启动前台service。
方法三:提升service优先级:
在AndroidManifest.xml文件中对于intent-filter可以通过android:priority = "1000"这个属性设置最高优先级,1000是最高值,如果数字越小则优先级越低,同时适用于广播。
二、在进程被杀死后,进行拉活
方法一:注册高频率广播接收器,唤起进程。如网络变化,解锁屏幕,开机等
方法二:双进程相互唤起。
方法三:依靠系统唤起。
方法四:onDestroy方法里重启service:service +broadcast 方式,就是当service走ondestory的时候,发送一个自定义的广播,当收到广播的时候,重新启动service;
三、依靠第三方
根据终端不同,在小米手机(包括 MIUI)接入小米推送、华为手机接入华为推送;其他手机可以考虑接入腾讯信鸽或极光推送与小米推送做 A/B Test。
三级缓存
优先访问内存中的图片缓存,若内存中没有,则加载本地SD卡中图片,最后选择访问网络
二、JAVA部分
1.sleep和wait的区别
1.sleep来自Thread类,和wait来自Object类
2.调用sleep方法的过程中,线程不会释放对象锁。而调用wait方法线程会释放对象锁
3.sleep睡眠后不出让系统资源,wait让出系统资源其他线程可以占用CPU
4.sleep需要指定一个睡眠时间,时间一到会自动唤醒
2.强引用、软引用、弱引用、虚引用
强引用,通过new创建的对象就是强引用
软引用,通过SoftReference类来实现。软引用的生命周期比强引用短一些。只有虚拟机认为内存不足时,再回收软引用指向的对象
弱引用,通过WeakReference类来实现。当垃圾回收器扫描到它管辖的内存区域时,一旦发现了弱引用的对象,不管内存空间是否充足,都回收它的内存
虚引用,用来做一些精细的内存控制操作
谈到这四种引用,先让我做个这样的比喻,JVM好比你,内存好比你的抽屉,你日常生活中必需品好比强引用,日常生活中可能用到的东西(即非必需品)好比软引用或弱引用。当你的抽屉还很空的时候,放些可能以后会用到的东西,你也不会在意。但随着你买了很多生活必需品时,但你的抽屉已放不下了且你又没有其他空间可以存放它们,这时你就会将根据一些重要程度选择一些东西扔出抽屉,这个过程就好比JVM垃圾回收,JVM在内存不紧张的时候,存放些软引用或弱引用所引用的对象以备后续使用,当内存紧张时就对它们进行清理。
3.ArrayList和LinkedList的区别
第一点,ArrayList是实现了基于动态数组的数据结构,而LinkedList是实现了基于链表的数据结构
第二点,对于随机访问操作get和set,ArrayList要优于LinkedList,因为LinkedList要移动指针
第三点,对于新增和删除操作add和remove,LinedList要优于ArrayList,因为ArrayList要移动数据
JAVA GC原理
垃圾收集算法的核心思想是:对虚拟机可用内存空间,即堆空间中的对象进行识别,如果对象正在被引用,那么称其为存活对象,反之,如果对象不再被引用,则为垃圾对象,可以回收其占据的空间,用于再分配。垃圾收集算法的选择和垃圾收集系统参数的合理调节直接影响着系统性能。
Thread中的start()和run()方法有什么区别
start()方法是用来启动新创建的线程,而start()内部调用了run()方法,这和直接调用run()方法是不一样的,如果直接调用run()方法,则和普通的方法没有什么区别
String,StringBuilder,StringBuffer区别
1、运行速度快慢为:StringBuilder > StringBuffer > String (由于String是常量,不可改变,拼接时会重新创建新的对象)
2、线程安全上:StringBuilder是线程不安全的,而StringBuffer是线程安全的(由于StringBuffer有缓冲区)
TCP和UDP的区别
TCP
是面向连接的,由于TCP连接需要三次握手,所以能够最低限度的降低风险,保证连接的可靠性。
UDP
不是面向连接的,udp建立连接前不需要与对象建立连接,无论是发送还是接收,都没有发送确认信号。所以说udp是不可靠的。由于udp不需要进行确认连接,使得UDP的开销更小,传输速率更高,所以实时行更好。
重载和重写的区别
1、重载:一个类中可以有多个相同方法名的,但是参数类型和个数都不一样。这是重载。
2、重写:子类继承父类,则子类可以通过实现父类中的方法,从而新的方法把父类旧的方法覆盖。
Http https区别
此处延伸:https的实现原理
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。