1.int、char、long、中文字符占用字节数
Java基本类型占用的字节数:
1字节: byte , boolean
2字节: short , char
4字节: int , float
8字节: long , double
注:1字节(byte)=8位(bits)
Unicode/GBK: 中文2字节
UTF-8: 中文通常3字节,在拓展B区之后的是4字节,中文字符在编码中占用的字节数一般是2-4个字节。
2.Service保活
1)onStartCommand返回START_STICKY
2)在Manifest里通过android:priority = "1000"这个属性设置最高优先级或android:persistent=“true”
3)通过系统的一些广播,比如:手机重启、界面唤醒的监听来拉活
4)系列应用相互唤醒
5)守护进程
3.Java虚拟机JVM的理解
Java虚拟机主要是平台无关性,Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。上图为JVM内存分布图,加上类加载器组成了JVM。比如在Android中它就是一个Linux进程,可以进性代码加载、垃圾回收
4.Java基本思想
面向对象:将独立个体(事物)的属性和行为封装
在一个类中,通过抽象和继承
实现个体间的相互影响、协作。形成了对象多态
和行为多态
的特性。
封装:描述事物的属性(成员变量)和描述事物的行为(成员方法)在类中用public、private、protected封装起来
抽象和继承:将对象的功能抽象到接口里去描述,继承则是子类可以使用父类的非私有属性和方法
多态:对象多态(类型转换、上下造型),行为多态(重写和重载)
5.Java多线程安全问题
问题的产生:多个线程在操作共享的数据,且操作共享数据的线程代码有多条。
问题的解决:同步代码块(锁对象可以是任意的对象);同步方法 (锁对象是this);静态同步方法(锁对象为本类类名.class);
6.sleep()和wait()方法的区别?
sleep(): Thread中的方法,不释放锁对象, 释放CPU使用权,在休眠的时间内,不能唤醒
wait(): Object中的方法,释放锁对象, 释放CPU使用权,在等待的时间内,能唤醒
Android相关
1.Activity之间、Activity与Service之间的通信方式
Activity之间可以通过Intent携带信息、静态变量共享、数据库SQLite与SharedPreference、Broadcast来进行;
Activity与Service之间除了上述,还可以使用Binder的方式进行,建立ServiceConnection;
2.ContentProvider、ContentResolver和ContentObserver
ContentProvider是Android的四大组件之一,主要的作用是:实现各个应用程序之间的(跨应用)数据共享;一个应用实现ContentProvider来提供内容给别的应用来操作, 通过ContentResolver来操作别的应用数据;ContentObserver——内容观察者,目的是观察(捕捉)特定Uri引起的数据库的变化,继而做一些相应的处理,当ContentObserver所观察的Uri发生变化时,便会触发它;
3.Android两种序列化的区别
1)由Java提供的序列化接口Serializable,使用时声明接口即可,而Parcelable是由Android SDK提供的一种序列化接口,使用时要实现内部相应的方法,其开销小效率高;
2)在读写数据的时候,Parcelable是在内存中直接进行读写,而Serializable是通过使用IO流的形式将数据读写入在硬盘上;
4.invalidate和postInvalidate的区别及使用
都是更新界面的,触发onDraw,invalidate只能在主线程调用,而postInvalidate可以在工作线程调用
5.Requestlayout,onlayout,onDraw,DrawChild区别与联系
requestLayout()方法 :会导致调用measure()过程 和 layout()过程 。 说明:只是对View树重新布局layout过程包括measure()和layout()过程,不会调用draw()过程,但不会重新绘制 任何视图包括该调用者本身。
onLayout()方法(如果该View是ViewGroup对象,需要实现该方法),对每个子视图进行布局
调用onDraw()方法绘制视图本身 (每个View都需要重载该方法,ViewGroup不需要实现该方法)
drawChild()去重新回调每个子视图的draw()方法
6.一次完整的网络请求流程
域名解析->建立TCP的连接->发起HTTP请求(GET、POST等方法)->服务器响应HTTP请求->解析并展示返回的内容。
7.Looper架构
Looper内部维护一个 MessageQueue和Thread ,Looper.loop()方法不断循环获取消息队列的Message(Queue的next方法)
ActivityThread的main方法主要就是做消息循环,一旦退出消息循环,那么你的应用也就退出了。
8.ActivityThread,ActivityManagerService(AMS),WindowManagerService(WMS)的工作原理
Activity只负责生命周期和事件处理,Window只控制视图;AMS统一调度所有应用程序的Activity,WMS控制所有Window的显示与隐藏以及要显示的位置
WindowManagerService为所有窗口分配Surface。添加一个窗口的过程,其实就是WMS为其分配一块Suiface的过程,一块块Surface在WMS的管理下有序的排布在屏幕上。而Window的本质就是Surface。管理Surface的显示顺序、尺寸、位置,管理窗口动画,输入系统相关;WindowManagerService是派发系统按键和触摸消息的最佳人选,当接收到一个触摸事件,它需要寻找一个最合适的窗口来处理消息,而WMS是窗口的管理者,系统中所有的窗口状态和信息都在其掌握之中,完成这一工作不在话下。WMS与SurfaceFling的一个重要区别就是——后者只做与“显示”相关的事情,而WMS要处理对输入事件的派发。
AMS作用:统一调度所有应用程序的Activity的生命周期;启动或杀死应用程序的进程;启动并调度Service的生命周期;注册BroadcastReceiver,并接收和分发Broadcast;启动并发布ContentProvider;调度task;处理应用程序的Crash;查询系统当前运行状态。
应用的启动:Launcher点击后通过Binder机制调用Service端ActivityMangerService调用startActivityXXX()方法
9.自定义View如何考虑机型适配
1)合理使用warp_content,match_parent适配;不同的机型,使用不同的布局文件放在对应的目录下,android会自动匹配;尽量使用点9图片,dp,sp等自适应像素的;自定义View可以使用缩放Scale
10.Activity的launchMode应用场景
standard,创建一个新的Activity。
singleTop,栈顶不是该类型的Activity,创建一个新的Activity。否则,onNewIntent。比如推送显示页面,新来的显示更新内容即可;
singleTask,回退栈中没有该类型的Activity,创建Activity,否则,onNewIntent+ClearTop。适合程序主入口点,比如浏览器主页面;
singleInstance,回退栈中,只有这一个Activity,没有其他Activity。适合需要与程序分离开的页面。
11.SparseArray原理
SparseArray稀疏数组,是android里为<Interger,Object>这样的Hashmap而专门写的类,目的是提高内存效率,内部采用折半查找;SparseArray执行效率比HashMap要慢一点,因为查找需要折半查找,而添加删除则需要在数组中执行,而HashMap都是通过外部映射
12.ListView 中图片错位的问题是如何产生的
ListView的可见Item请求图片时滑动,由于复用了convertView,图片请求成功后会显示到复用这个convertview的Item上产生错位;解决方法很简单,对ImageView设置Tag为url,显示时判断url是否匹配传入的url
13.混合开发
Hybrid App(混合模式移动应用)是指介于web-app、native-app这两者之间的app,兼具“Native App良好用户交互体验的优势”和“Web App跨平台开发的优势”。这里只是说一下概念,至于了解程度看个人了。
14.动态权限适配方案,权限组的概念
Android6.0以上对一些危险权限使用动态适配,使用时需要调用checkSelfPermission来动态申请权限;权限组是指同一组的任何一个权限被授权了,其他权限也自动被授权
15.Java中强引用置为null,会不会被回收
把强应用置为null实际就是告诉虚拟机该对象可以回收了,因此可能在下一次垃圾回收时被回收。
16.String为什么Java要设置成不可变(final)
1)字符串常量池的需要,字符串常量池(String pool, String intern pool, String保留池) 是Java堆内存中一个特殊的存储区域, 当创建一个String对象时,假如此字符串值已经存在于常量池中,则不会创建一个新的对象,而是引用已经存在的对象。
2)允许String对象缓存HashCode,字符串不变性保证了hash码的唯一性,因此可以放心地进行缓存.这也是一种性能优化手段,意味着不必每次都去计算新的哈希码.
3)安全性 因为字符串是不可变的,所以它的值是不可改变的,否则黑客们可以钻到空子,改变字符串指向的对象的值,造成安全漏洞。
17. 使用Semaphore控制某个方法允许并发访问的线程的个数
Semaphore有两个重要的方法,semaphore.acquire() 请求一个信号量,这时候的信号量个数-1(一旦没有可使用的信号量,也即信号量个数变为负数时,再次请求的时候就会阻塞,直到其他线程释放了信号量),semaphore.release() 释放一个信号量,此时信号量个数+1。在线程里开启时申请一个信号量,当线程开启达到预设上限时,新线程就会阻塞,直到有信号量被释放。
18.Android版本兼容性问题
compileSdkVersion -- 编译项目所用的SDK版本
minSdkVersion -- App运行设备所需支持的最小SDK版本(不仅在安装时起作用,在项目构建时也会起作用)
targetSdkVersion -- 该设备的SDK版本无需系统开启兼容模式保证程序正常运行
maxSdkVersion -- 标明App所能运行的最高设备版本号
API的变更引起的问题如何做兼容性处理呢:
(1)平台判断,旧平台使用旧的API,新平台使用新的API:使用TargetApi或SuppressLint注解标注;build.Version.SDK_INT运行时判断。
(2)用反射的方式调用高版本中的新功能接口进行调用。
(3)分离代码,分别在不同的SDK上编译运行,最后classLoader加载高版本中的相关类接口。
(4)官方support类库,如support-v13。
19.Android UI更新方案
1. 可以明确地说,Android不允许在子线程更新UI,只能在main主线程进行,否则会抛出异常;
2. 最常见的是利用主线程的Handler,子线程完成任务后,向该Handler发送消息,消息的处理就是在主线程进行;
3. AsyncTask利用线程任务异步更新UI界面,其中doInBackground执行后台任务,onProgressUpdate可用UI于刷新进度,onPostExecute可用于UI显示结果;
4. Activity.runOnUiThread()方案:子线程处理任务,runOnUiThread用于显示任务结果到UI上;
20.TextView.setText()耗时原因
当textview的宽设置为wrap_content的时候,底层会调用checkForRelayout函数,这个函数根据文字的多少重新开始布局,因此将宽度设置为固定值或者match_parent的时候会大幅度减少绘制时间