经典Android面试题
1.解释下在单线程模型中Message,Handler,Message Queue,Looper之间的关系。
主线程中,主线程启动时会调用Looper.prepare()方法,会初始化一个Looper,放入Threadlocal中,接着调用Looper.loop()遍历Message Queue; Handler的创建依赖与当前线程中的Looper,如果当前线程没有Looper则必须调用Looper.prepare()。Handler,sendMessage到MessageQueue,Looper不断从MessageQueue中取出消息,回调handleMeaage方法。
2.内存溢出和内存泄漏的区别?何时会产生内存泄漏?内存优化有哪些方法?
内存溢出:应用程序运行时需要的内存,超出了它可用的最大内存
内存泄漏:针对某一内存空间的使用,使用完成后没有释放。
内存优化:Android中容易内存溢出的部分,就是图片的加载,我们可以使用图片的压缩加上使用LruCache缓存的方法来控制图片所能够使用的内存
除此之外,对于比较耗资源的对象及时的关闭,比如service、conn、各类传感器、Database,屏幕旋转,整个Activity对象会有泄漏。
解决办法(避免内存泄漏没有简单的解决方案,但Android提供的工具和API可以提供帮助):DDMS视图中,可以使用Heap及Alloction Tracker跟踪内存使用和分配情况。 Android2.3定义StrictMode类,对检测潜在的内存泄漏有很大帮助,但在3.0以上版本中,可以检测的潜在内存泄漏的情况有:
1.activity泄漏
2.其他对象泄漏
3.对象没有关闭造成的泄漏
3.AsyncTask使用在哪些场景?它的缺陷是什么?如何解决?
AsyncTask运用的场景是需要进行一些耗时的操作,耗时操作完成时更新主线程,或者在操作过程中对主线程的UI进行更新
缺陷:AsyncTask中维护着一个长度为128的线程池,同时可以执行5个工作线程,还有一个缓冲队列,当线程池中已有128个线程,缓冲队列已满,如果此时向线程提交任务,将会抛出RejectedExecutionException
处理:由一个线程来处理AsyncTask的调用判断线程池是否满了,如果满了线程睡眠否则请求AsyncTask继续处理。
4.context的作用是什么?一个APP最多会创建多少个Context对象?
①context是一个抽象类,其通用实现在ContextImpl类中。
②Context是一个访问application环境全局信息的接口,通过它可以访问application的资源和相关类,其主要功能如下:
启动Activity 启动和停止Service 发生广播消息(Intent) 注册广播消息接收者
可以访问APK中各种资源(Resources 和 AssetManager等)
可以访问Package的相关信息 APK的各种权限管理
从以上可以看出,Context就是一个对APK包无所不知的大管家,想知道什么信息,就去访问它就可以了
Context与View的关系
ContextWrapper
它只是对Context类的一种封装,它的构造函数包含了一个真正的Context引用,即ContextImpl对象
ContextThemeWrapper
该类包含了主题(Theme)相关接口,即安卓theme指定的,因为service不需要theme,所以Service直接继承ContextWrapper
何时创建Context
①创建Application对象时
②创建service对象时
③创建Activity对象时
因此应用程序App共有的Context数目公式为:
总Context实例个数 = NUM(Activity) + NUM(Service) + 1(Application)
5.写出并描述Service和Activity的交互方式
6.Android开发过程中如何进行算法与界面的优化?
挑战程序的进程结构,减少进程数量,减少进程周期循环次数,即时让线程休眠,不编写长寿代码,只在需要时运行,服务应快速完成并立即结束。
调整算法,取消不必要的环节,减少对CPU和内存的需求,减少函数的调用次数,适当使用JNI
精心设计界面避免复杂布局,控制嵌套和View数量,善用Merge、inflate()、RelativeLayout等去除不必要的背景、动画执行长时间、好点的任务前检查电量,提示用户
7.
================================================java====================================================
1.计算下列result的值
int a = 1234567;
int b = 0x06;
int result = a&b; 6
二进制&运算,很简单,转化成二进制进行与运算,一定不要犯懒,我就是犯懒没有计算a的二进制,结果自己就悲剧了。。。
2.抽象类与接口的区别?
abstract可以修饰抽象方法,而一个类主要有一个抽象方法,就必须用abstract定义该类,即抽象类。
用interface修饰的类,里面的方法都是抽象方法,因此在定义接口的时候,可以直接不加那些修饰,系统会默认加上去,接口里面的字段都是共有常量,即public static final
3.集合实现类与区别?
Collection接口、集合结构总的父接口,有两个子接口list和set
list有序,元素可重复 实现类:ArrayList数组实现轻量级、运行快、线程不安全、查询快
Vectot数组实现重量级,运行慢、线程安全
LinkedList 链表实现,常用于堆栈与队列的实现 增删操作快
set接口 元素无序不重复
实现类:HashSet,底层用hashCode算法实现,保证元素的无序唯一,自定义对象存进HashSet为了保证元素内容不重复,需要重写hashCode()和equals()方法。
SortedSet元素有序 唯一
TreeSet要求元素有序,自定义的对象需要实现Comparable接口的compareTo(Object o)方法
Map:与Collection接口无关,有一个子接口SortedMap 无序,key-value对,key唯一,value可重复
HashMap轻量级 线程不安全,允许key或value为null
HashTable 重量级 线程安全 不允许key或vaule为null
Properties是HashTable的子类,主键和值都是字符串
4.线程的状态有几种?分别是什么?
1)新建状态:创建了一个线程对象。
2)就绪状态:线程对象创建后,其他线程调用了该对象的start方法。该状态的线程位于可运行线程池中,变得可运行,等待CPU的使用权
3)运行状态:就绪状态的线程获得了CPU,执行run()方法
4)阻塞状态:阻塞状态是因为线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,线程才有机会继续运行。阻塞情况分为3中