Service生命周期
1、service 启动方式有两种,一种是通过startService()方式进行启动,另一种是通过bindService()方式进行启动。
startService()这种方式启动的service,生命周期是这样:调用startService() --> onCreate()--> onStartConmon()--> onDestroy()。这种方式启动的话,第一:通过startService被调用以后,多次在调用startService(),onCreate()方法也只会被调用一次,而onStartConmon()会被多次调用当我们调用stopService()的时候,onDestroy()就会被调用,从而销毁服务。
bindService()方式进行绑定,这种方式绑定service,生命周期走法:bindService-->onCreate()-->onBind()-->unBind()-->onDestroy() bindservice 这种方式进行启动service好处是更加便利activity中操作service,在activity获取ServiceConnection对象,通过ServiceConnection来获取service中内部类的类对象,然后通过这个类对象就可以操作。
2、Broadcast注册方式与区别
第一种是静态注册,也可成为常驻型广播,这种广播需要在Androidmanifest.xml中进行注册,这中方式注册的广播,不受页面生命周期的影响,即使退出了页面,也可以收到广播这种广播一般用于想开机自启动啊等等,由于这种注册的方式的广播是常驻型广播,所以会占用CPU的资源。
第二种是动态注册,而动态注册的话,是在代码中注册的,这种注册方式也叫非常驻型广播,收到生命周期的影响,退出页面后,就不会收到广播,我们通常运用在更新UI方面。这种注册方式优先级较高。最后需要解绑,否则会内存泄露。
3、HttpClient与HttpUrlConnection的区别
首先HttpClient和HttpUrlConnection 这两种方式都支持Https协议,都是以流的形式进行上传或者下载数据等功能。HttpClient这个拥有非常多的API,很难进行兼容扩展,而HttpUrlConnection相对来说就是比较轻量级了,API比较少,容易扩展;
Java虚拟机:
1、java虚拟机基于栈。
2、java虚拟机运行的是java字节码。(java类会被编译成一个或多个字节码.class文件)
Dalvik虚拟机:
1、dalvik虚拟机是基于寄存器的
2、Dalvik运行的是自定义的.dex字节码格式。(java类被编译成.class文件后,会通过一个dx工具将所有的.class文件转换成一个.dex文件,然后dalvik虚拟机会从其中读取指令和数据
5、进程保活(不死进程)
当前业界的Android进程保活手段主要分为** 黑、白、灰 **三种,其大致的实现思路如下:
黑色保活:不同的app进程,用广播相互唤醒(包括利用系统提供的广播进行唤醒){利用不同的app进程使用广播来进行相互唤醒:开机广播、三方sdk}
白色保活:调用系统api启动一个前台的Service进程,这样会在系统的通知栏生成一个Notification
灰色保活:利用系统的漏洞启动前台Service,它不会在系统通知栏处出现一个Notification,看起来就如同运行着一个后台Service进程一样,大致的实现思路如下:
1 API < 18,启动前台Service时直接传入new Notification();
2 API >= 18,同时启动两个id相同的前台Service,然后再将后启动的Service做stop处理
用C编写守护进程(即子进程) : Android系统中当前进程fork出来的子进程,被系统认为是两个不同的进程。当父进程被杀死的时候,子进程仍然可以存活。
5、讲解一下Context
Context是一个抽象基类。翻译为上下文,是提供一些程序的运行环境基础信息。Context下有两个子类,ContextWrapper是上下文功能的封装类,而ContextImpl则是上下文功能的实现类。 ContextWrapper又有三个直接的子类, ContextThemeWrapper、Service和Application。其中,ContextThemeWrapper是一个带主题的封装类,而它有一个直接子类就是Activity, Context一共有三种类型,Application、Activity和Service。它们都属于Context的一种,而它们具体的功能则是由ContextImpl类去实现的,因此在绝大多数场景下,Activity、Service和Application这三种类型的Context都是可以通用的,特殊场景只能使用Activity类型的Context。
6、四种LaunchMode及其使用场景
standard 模式
这是默认模式,每次激活Activity时都会创建Activity实例,并放入任务栈中。使用场景:大多数Activity。
singleTop 模式
如果在任务的栈顶正好存在该Activity的实例,就重用该实例,否则就会创建新的实例并放入栈顶,即使栈中已经存在该Activity的实例,只要不在栈顶,都会创建新的实例。
singleTask 模式
如果在栈中已经有该Activity的实例,会让该实例回到栈顶,因此在它上面的实例将会被移出栈。如果栈中不存在该实例,将会创建新的实例放入栈中。
singleInstance
这种启动模式比较特殊,因为它会启用一个新的栈结构,将Acitvity放置于这个新的栈结构中,并保证不再有其他Activity实例进入
7、Android中的几种动画
帧动画:指通过指定每一帧的图片和播放时间,有序的进行播放而形成动画效果,比如想听的律动条。
补间动画:指通过指定View的初始状态、变化时间、方式,通过一系列的算法去进行图形变换,从而形成动画效果,主要有Alpha、Scale、Translate、Rotate四种效果。注意:只是在视图层实现了动画效果,并没有真正改变View的属性,比如滑动列表,改变标题栏的透明度。
属性动画:在Android3.0的时候才支持,通过不断的改变View的属性,不断的重绘而形成动画效果。相比于视图动画,View的属性是真正改变了。比如view的旋转,放大,缩小。
8、Binder机制原理
在Android系统的Binder机制中,是有Client,Service,ServiceManager,Binder驱动程序组成的,其中Client,service,Service Manager运行在用户空间,Binder驱动程序是运行在内核空间的。而Binder就是把这4种组件粘合在一块的粘合剂,其中核心的组件就是Binder驱动程序,Service Manager提供辅助管理的功能,而Client和Service正是在Binder驱动程序和Service Manager提供的基础设施上实现C/S 之间的通信。其中Binder驱动程序提供设备文件/dev/binder与用户控件进行交互,Client、Service,Service Manager通过open和ioctl文件操作相应的方法与Binder驱动程序进行通信。而Client和Service之间的进程间通信是通过Binder驱动程序间接实现的。而Binder Manager是一个守护进程,用来管理Service,并向Client提供查询Service接口的能力。
1. 从IPC角度来说,Binder是Android中的一种跨进程通信方式,Binder还可以理解为一种虚拟的物理设备,它的设备驱动是/dev/binder,该通信方式在linux中没有
2. 从Android Framework角度来说,Binder是ServiceManager连接各种Manager(ActivityManager、WindowManager,etc)和相应ManagerService的桥梁
3. 从Android应用层来说,Binder是客户端和服务端进行通信的媒介,当你bindService的时候,服务端会返回一个包含了服务端业务调用的Binder对象,通过这个Binder对象,客户端就可以获取服务端提供的服务或者数据,这里的服务包括普通服务和基于AIDL的服务
1、同进程中Activity和Service进行通讯时候,用到binder,在Activity中对Servrice进行操作
2、不同进程可以用AIDL让系统创建一个Binder,然后Activity对远端的service进行操作。
9、AIDL理解
AIDL: 每一个进程都有自己的Dalvik VM实例,都有自己的一块独立的内存,都在自己的内存上存储自己的数据,执行着自己的操作,都在自己的那片狭小的空间里过完自己的一生。而aidl就类似与两个进程之间的桥梁,使得两个进程之间可以进行数据的传输,跨进程通信有多种选择,比如 BroadcastReceiver , Messenger 等,但是 BroadcastReceiver 占用的系统资源比较多,如果是频繁的跨进程通信的话显然是不可取的;Messenger 进行跨进程通信时请求队列是同步进行的,无法并发执行。
10、热修复的原理
Tinker热修复 :是微信官方发布的 Android 热补丁解决方案,它支持动态下发代码、So库以及资源,让应用能够在不需要重新安装的情况下实现更新;
原理:Tinker都利用了Android 的类加载机制,Android中有两个主要的Classloader,PathClassLoader和DexClassLoader,它们都继承自BaseDexClassLoader,Android系统通过PathClassLoader来加载系统类和主dex中的类。而DexClassLoader则可用于加载指定路径的apk、jar或dex文件。BaseDexClassLoader 中调用findClass,这个方法中会遍历dexpathlist中的dexElements数组,然后初始化DexFile。ClassLoader在加载到正确的类之后就会停止加载此类,因此我们将包含正确的类的Dex文件中插入在dexElements数组前面就可以完成对问题类的修复
流程:启动应用-》有无fix_classes.dex文件-》下载补丁 patch.dex-》开启TinkerPathService 和旧dex文件合并生成全量dex-》重新启动把这个全量dex elements前面 –》完成修复
11、Android UI适配
字体使用sp,使用dp,多使用match_parent,wrap_content,weight
图片资源,不同图片的的分辨率,放在相应的文件夹下可使用百分比代替。
12、JAVA GC原理
垃圾收集算法的核心思想是:对虚拟机可用内存空间,即堆空间中的对象进行识别,如果对象正在被引用,那么称其为存活对象
,反之,如果对象不再被引用,则为垃圾对象,可以回收其占据的空间,用于再分配。垃圾收集算法的选择和垃圾收集系统参数的合理调节直接影响着系统性能。
13、ANR
ANR全名Application Not Responding, 也就是"应用无响应". 安卓应用程序是由活动管理器和窗口管理器来监听的
产生原因:
(1)app5s内无法响应用户输入事件(例如键盘输入, 触摸屏幕等).
(2)BroadcastReceiver在10s内无法结束
(3)Service 20s内无法结束(低概率)
解决方式:
(1)不要在主线程中做耗时的操作,而应放在子线程中来实现。如onCreate()和onResume()里尽可能少的去做创建操作。
(2)应用程序应该避免在BroadcastReceiver里做耗时的操作或计算。
(3)避免在Intent Receiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。
(4)service是运行在主线程的,所以在service中做耗时操作,必须要放在子线程中。
14、RecyclerView和ListView的区别
RecyclerView可以完成ListView,GridView的效果,还可以完成瀑布流的效果及列表的滚动方向(垂直或者水平);RecyclerView提供了API来实现item的动画效果;RecyclerView还可以组合展示不同类型的view。
在性能上:
如果需要频繁的刷新数据,需要添加动画,则RecyclerView有较大的优势。
如果只是作为列表展示,则两者区别并不是很大。
15、static
1、static变量:对于静态变量在内存中只有一个拷贝(节省内存),JVM只为静态分配一次内存,
在加载类的过程中完成静态变量的内存分配,可用类名直接访问(方便),当然也可以通过对象来访问(但是这是不推荐的)。
2、static代码块
static代码块是类加载时,初始化自动执行的。
3、static方法
static方法可以直接通过类名调用,任何的实例也都可以调用,因此static方法中不能用this和super关键字,
不能直接访问所属类的实例变量和实例方法(就是不带static的成员变量和成员成员方法),只能访问所属类的静态成员变量和成员方法。
16、String,StringBuffer,StringBuilder区别
1、三者在执行速度上:StringBuilder > StringBuffer > String (由于String是常量,不可改变,拼接时会重新创建新的对象)。
2、StringBuffer是线程安全的,StringBuilder是线程不安全的。(由于StringBuffer有缓冲区)
Java中重载和重写的区别:
1、重载:一个类中可以有多个相同方法名的,但是参数类型和个数都不一样。这是重载。
2、重写:子类继承父类,则子类可以通过实现父类中的方法,从而新的方法把父类旧的方法覆盖。
17、网络 Http https区别
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https端口不一样,前者是80,后者是443。
7、Http位于TCP/IP模型中的第几层?为什么说Http是可靠的数据传输协议?
tcp/ip的五层模型:
从下到上:物理层->数据链路层->网络层->传输层->应用层
其中tcp/ip位于模型中的网络层,处于同一层的还有ICMP(网络控制信息协议)。http位于模型中的应用层(先有ip在tcp)
由于tcp/ip是面向连接的可靠协议,而http是在传输层基于tcp/ip协议的,所以说http是可靠的数据传输协议。
8、HTTP链接的特点
HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。
从建立连接到关闭连接的过程称为“一次连接”。
9、TCP和UDP的区别
tcp是面向连接的,由于tcp连接需要三次握手,所以能够最低限度的降低风险,保证连接的可靠性。
udp 不是面向连接的,udp不需要与对象建立连接,无论是发送还是接收,都没有发送确认信号。所以说udp是不可靠的。
由于udp不需要进行确认连接,使得UDP的开销更小,传输速率更高,所以实时行更好。
10、Socket建立网络连接的步骤
建立Socket连接至少需要一对套接字,其中一个运行与客户端--ClientSocket,一个运行于服务端--ServiceSocket
1、服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。
2、客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。注意:客户端的套接字必须描述他要连接的服务器的套接字,
指出服务器套接字的地址和端口号,然后就像服务器端套接字提出连接请求。
3、连接确认:当服务器端套接字监听到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述
发给客户端,一旦客户端确认了此描述,双方就正式建立连接。而服务端套接字则继续处于监听状态,继续接收其他客户端套接字的连接请求。
17、内存管理区域:
共享数据区:
方法区:存放类信息、常量、静态变量、编译器编译后的代码等数据
堆:对象分配内存的区域
线程私有 :
虚拟机栈:方法执行的内存区,每个方法执行时会在虚拟机栈中创建栈帧;
本地方法栈:虚拟机的Native方法执行的内存区
程序计数器:记录正在执行的虚拟机字节码的地址
18、JAVA中堆和栈的区别
基本数据类型变量和对象 的引用都是在栈中
堆内存用来存放由new创建的对象和数组
static修饰的变量,程序在一加载的时候就在堆中为类变量分配内存,堆中的内存地址存放在栈中
实例变量:当你使用java关键字new的时候,系统在堆中开辟间分配给变量
局部变量:由声明在某方法,或某代码段里(比如for循环),执行到它的时候在栈中开辟内存,当局部变量一但脱离作用域,内存立即释放
19、XML解析
解析XML的几种方式的原理与特点:DOM、SAX、PULL
SAX和pull 基于事件驱动的流动解析,解析速度快,占内存少
DOM消耗内存 ;先把xml文档都读到内存中,然后在访问各个节点
20、Dalvik和ART的区别:
在Dalvik下,应用每次运行时都会执行转换机器码操作;
在ART下,应用在第一次安装的时候,字节码就会预先转换成机器码
优点:运行快缺点:1.机器码占用的存储空间更大 2.应用的安装时间会变长
21、JNI(Java Native Interface 本地接口语言)的操作步骤:
·编写带有native声明的方法的java类
·使用javac命令编译所编写的java类
·使用javah 对java类生成扩展名为h的头文件
·使用C/C++(或者其他编程想语言)实现本地方法
·将C/C++编写的文件生成动态连接库
21 、IntentService
IntentService,可以看做是Service和HandlerThread的结合处理耗时操作。当任务执行完后,IntentService 会自动停止,不需要我们去手动结束。
22、多线程断点下载 实现过程
①、首先使用HttpURLConnection.getContentLength()获取下载文件的长度,然后设置本地文件的长度。
②、根据下载文件长度和线程数计算每条线程下载的数据长度和下载的位置。
③、使用HTTP的请求头字段Range指定每条线程从文件的什么位置开始下载,到什么位置下载结束。
④、保存文件。使用RandomAccessFile类指定每条线程从本地文件的什么位置开始写入数据。
23、 线程池
1.避免线程频繁创建消毁。多个线程频繁地销毁,会频繁地调用GC机制,这会使性能降低。
2.避免系统资源紧张。多个线程频繁的创建会占用大量的资源,缺乏统一的管理,在资源竞争时容易出现问题造成界面卡顿。
3.更好地管理线程。以下载功能为例,可以很好的控制下载任务:下载数,下载顺序队列等。
newFixedThreadPool(固定数量线程池):数量固定,适用于为了满足资源管理的需求,而限制当前线程数,它适用于负载比较重的服务器。优点:更快的响应外界请求
newCachedThreadPool:(缓存线程池)线程数非常大,任何任务都会被立即执行,比较适合执行大量的耗时较少的任务.
newSingleThreadExecutor(单利线程池):保证顺序地执行各个任务;并且不会有多个线程活动,不需要处理线程同步的问题
newScheduledThreadPool:(定时线程池)主要在给定的延迟之后运行任务,或者定期执行任务,例如定时轮询数据库中的表的数据
24、java 基本设计模式
23种模式: 设计模式主要分三个类型:创建型、结构型和行为型。
其中创建型有:
1、单例模式:单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例单例模式;
2、观察者模式:观察者模式属于行为型模式,定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
事件通知也是观察者模式。
3、工厂模式:定义了一个创建对象的接口,让子类来决定具体实例化哪一个类
4、适配器模式:ListView或GridView的Adapter 简介:不同的数据提供者使用一个适配器来向一个相同的客户提供服务。
5、建造者模式:AlertDialog.Builder 简介:可以分步地构造每一部分。
6、命令模式:Handler.post后Handler.handleMessage 简介:把请求封装成一个对象发送出去,方便定制、排队、取消。
25、Android 网络通信机制
Android平台有三种网络接口可以使用,他们分别是:java.net.*(标准Java接口)、Org.apache接口和Android.net.*(Android网络接口)。
1,java.net.* (标准java接口) HttpURLConnection 获取链接信息,
2,Apache接口 :HttpClient。它是一个开源项目,功能丰富.
3,Android网络接口 : Socket 套接字通信
26、handler机制的原理
andriod提供了 Handler 和 Looper 来满足线程间的通信.
1)Looper: 一个线程可以产生一个Looper对象,由它来管理此线程里的Message Queue(消息队列)。
2)Handler: Handler 先进先出原则,构造Handler对象来与Looper沟通,以便push新消息到Message Queue里;或者接收Looper从Message Queue取出)所送来的消息。
3)Message Queue(消息队列):用来存放线程放入的消息。
4)线程:UI thread 通常就是main thread,而Android启动程序时会替它建立一个Message Queue。
27、多渠道打包
美团的方案,直接解压apk,解压后的根目录会有一个META-INF目录,在目录下添加不同渠道的空文件唯一标识,类似 channel_xxx 的空文件, 在Java代码中解析这个文件名获取市场xxx即可
28、SurfaceView和view的区别
SurfaceView中采用了双缓冲机制,保证了UI界面的流畅性,同时SurfaceView不在主线程中绘制,而是另开辟一个线程去绘制,所以它不妨碍UI线程;
SurfaceView继承于View,他和View主要有以下三点区别:
(1)SurfaceView底层采用双缓冲机制,View没有;
(2)SurfaceView适用与被动的更新,如频繁的刷新,view主要适用于主动更新
(3)SurfaceView在子线程中刷新UI,view会在主线程中去更新;
29Serializable与Parcable的区别
为了保存对象的字节序列到本地文件里,在网络中传递对象需要做序列化处理
Serializable Java 在硬盘上读写, 读写过程中有大量临时变量的生成,会频繁GC,效率低。
Parcelable Android 在内存中读写,效率高 ,对象不能保存到磁盘中
30、Devik 进程,linux 进程,线程的区别
Dalvik进程。每一个android app都会独立占用一个dvm虚拟机,运行在linux系统中。
所以dalvik进程和linux进程是可以理解为一个概念。一个进程可以包含多个线程运行。
31、Android 程序运行时权限与文件系统权限的区别
文件的系统权限是由linux系统规定的,只读,读写等。
运行时权限,是对于某个系统上的app的访问权限,允许,拒绝,询问。该功能可以防止非法的程序访问敏感的信息。
32、ArrayMap和HashMap的对比
1、HashMap重新创建对象,开销很大。ArrayMap用的是copy数据,所以效率相对要高。
2、ArrayMap提供了数组收缩的功能,在clear或remove后,会重新收缩数组,是否空间
33、HashMap和HashTable的区别
HashMap不是线程安全的,效率高一点、方法不是Synchronize的要提供外同步。
hashtable是,线程安全,不允许有null的键和值,效率稍低,方法是是Synchronize的。/
34、HashMap与HashSet的区别
hashMap:HashMap实现了Map接口,HashMap储存键值对,使用put()方法将元素放入map中,HashSet实现了Set接口,HashSet仅仅存储对象,使用add()方法将元素放入set中,HashSet较HashMap来说比较慢
35、ArrayList和LinkedList的区别
ArrayList是线程不安全,基于数组实现的
LinkedList是基于双链表实现的;
(1)如果应用程序对各个索引位置的元素进行大量的存取或删除操作,ArrayList对象要远优于LinkedList对象;
( 2 ) 如果应用程序主要是对列表进行循环,并且循环时候进行插入或者删除操作,LinkedList对象要远优于ArrayList对象;
36、数组和链表的区别
数组:将元素在内存中连续存储,随机访问性强,查找速度快,数组大小固定,不能动态拓展,插入和删除效率低
链表:是动态申请内存空间,大小没有固定,拓展很灵活,插入删除速度快,不能随机查找,必须遍历,查找效率低
37、Rxjava:响应式编程主要采用观察者模式进行开发,即观察者订阅可观察的。可观察的(Observable)通过调用观察者的方法来发射事件给它的所有观察者(observer)
38、自定义View的基本流程
①.自定义View的属性 编写attr.xml文件
②.在layout布局文件中引用,同时引用命名空间
③.在View的构造方法中获得我们自定义的属性 ,在自定义控件中进行读取(构造方法拿到attr.xml文件值)
④.重写onMesure
⑥.重写onDraw
39、如何优化ListView
①Item布局,层级越少越好,使用hierarchyview工具查看优化。
②复用convertView
③使用ViewHolder
④item中有图片时,异步加载
⑤快速滑动时,不加载图片
⑥item中有图片时,应对图片进行适当压缩
40、设备横竖屏切换的时候,生面周期的变化
不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
设置Activity的android:configChanges=”orientation”时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
设置Activity的android:configChanges=”orientation|keyboardHidden”时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法
41、沉浸式实现:
Android4.4(API 19)实现方式为: 通过FLAG_TRANSLUCENT_STATUS设置状态栏为透明并且为全屏模式, 然后通过添加一个与StatusBar 一样大小的View,将View 的 background 设置为我们想要的颜色,从而来实现沉浸式。
Android 5.0(API 21)以上版本: 在Android 5.0的时候,加入了一个重要的属性和方法 android:statusBarColor (对应方法为 setStatusBarColor),直接绘制状态栏的背景。
Android 6.0是改变状态栏字体颜色: 获取DecorView 包含状态栏和布局的contentView因此对获取 decorView 设置一些沉浸式模式的UI Flag View decorView=getWindow().getDecorView(); intoption=View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LAYOUT_STABLE; decorView.setSystemUiVisibility(option); getWindow().setStatusBarColor(Color.TRANSPARENT)