概述
1,ANR产生的原因和处理?
ANR的产生需要同时满足三个条件:
-
主线程:只有应用程序进程的主线程响应超时才会产生ANR;
-
超时时间:产生ANR的上下文不同,超时时间也会不同,但只要在这个时间上限内没有响应就会ANR;
-
输入事件/特定操作:输入事件是指按键、触屏等设备输入事件,特定操作是指BroadcastReceiver和Service的生命周期中的各个函数,产生ANR的上下文不同,导致ANR的原因也会不同;
主线程在执行BroadcastReceiver的onReceive函数时10秒内没有执行完毕
主线程在执行Service的各个生命周期函数时20秒内没有执行完毕
三种ANR发生时都会在log中输出错误信息,你会发现各个应用进程和系统进程的函数堆栈信息都输出到了一个/data/anr/traces.txt的文件中,这个文件是分析ANR原因的关键文件,同时在日志中还会看到当时的CPU使用率
发生ANR时Android为我们提供了两种“利器”:traces文件和CPU使用率
2,HashMap的实现
哈希表是由数组+链表组成的,一个长度为16的数组中,每个元素存储的是一个链表的头结点。那么这些元素是按照什么样的规则存储到数组中呢。一般情况是通过hash(key)%len获得,也就是元素的key的哈希值对数组长度取模得到。
解决hash冲突的办法
- 开放定址法(线性探测再散列,二次探测再散列,伪随机探测再散列)
- 再哈希法
- 链地址法
- 建立一个公共溢出区
再散列rehash过程
当哈希表的容量超过默认容量时,必须调整table的大小。当容量已经达到最大可能值时,那么该方法就将容量调整到Integer.MAX_VALUE返回,这时,需要创建一张新表,将原表的映射到新表中。
3,Service 两种启动方式
1通过startService
Service会经历onCreate->onStart
stopService的时候直接onDestroy
如果是调用者(TestServiceHolder)自己直接退出而没有调用stopService的话,Service会一直在后台运行。
下次TestServiceHolder再起来可以stopService。
2通过bindService
Service只会运行onCreate,这个时候TestServiceHolder和TestService绑定在一起
TestServiceHolder退出了,Srevice就会调用onUnbind->onDestroyed
所谓绑定在一起就共存亡了。
4,Android跨进程通信
一、访问其他应用程序的Activity
Activity的跨进程访问与进程内访问略有不同。虽然它们都需要Intent对象,但跨进程访问并不需要指定Context对象和Activity的 Class对象,而需要指定的是要访问的Activity所对应的Action(一个字符串)。有些Activity还需要指定一个Uri(通过 Intent构造方法的第2个参数指定)。
二、Content Provider
1. 编写一个继承于android.content.ContentProvider的子类。该类是ContentProvider的核心类。在该类中会实现 query、insert、update及delete方法。实际上调用ContentResolver类的这4个方法就是调用 ContentProvider类中与之要对应的方法。在本文中只介绍query。至于insert、update、delete和query的用法类 似。也是通过Uri传递参数,然后在这些方法中接收这些参数,并做进一步地处理。
2. 在AndroidManifest.xml文件中配置ContentProvider。要想唯一确定一个ContentProvider,需要指定这个 ContentProvider的URI,除此之外,还需要指定URI所对应的ContentProvider类。这有些象Servlet的定义,除了要 指定Servlet对应的Web地址,还要指定这个地址所对应的Servlet类
3,广播(Broadcast)
4,AIDL服务
1. 在Eclipse工程的package目录中建立一个扩展名为aidl的文件。package目录就是Java类所在的目录。该文件的语法类似于Java代码。aidl文件中定义的是AIDL服务的接口。这个接口需要在调用AIDL服务的程序中访问。
2. 如果aidl文件的内容是正确的,Eclipse插件会自动生成一个Java接口文件(*.java)。
3. 建立一个服务类(Service的子类)。
4. 实现由aidl文件生成的Java接口。
5. 在AndroidManifest.xml文件中配置AIDL服务,尤其要注意的是,<action>标签的android:name属性值就是客户端要引用该服务的ID,也就是Intent类构造方法的参数值。
在编写AIDL服务和客户端时要注意如下两点:
5,堆和栈的区别
栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其 操作方式类似于数据结构中的栈。
堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回 收。
碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出,在他弹出之前,在他上面的后进的栈内容已经被弹出,详细的可以参考数据结构,这里我们就不再一一讨论了。
生长方向:对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。
分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。
分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。
6,Android平台体系结构中的虚拟机与JAVA中的虚拟机有什么不同
Dalvik 和标准Java 虚拟机(JVM)首要差别
Dalvik 基于寄存器,而 JVM 基于栈。基于寄存器的虚拟机对于更大的程序来说,在它们编译的时候,花费的时间更短。
Dalvik 和Java 运行环境的区别
1:Dalvik主要是完成对象生命周期管理,堆栈管理,线程管理,安全和异常管理,以及垃圾回收等等重要功能。
2:Dalvik负责进程隔离和线程管理,每一个Android应用在底层都会对应一个独立的Dalvik虚拟机实例,其代码在虚拟机的解释下得以执行。
3:不同于Java虚拟机运行java字节码,Dalvik虚拟机运行的是其专有的文件格式Dex
4:dex文件格式可以减少整体文件尺寸,提高I/o操作的类查找速度。
5:odex是为了在运行过程中进一步提高性能,对dex文件的进一步优化。
6:所有的Android应用的线程都对应一个Linux线程,虚拟机因而可以更多的依赖操作系统的线程调度和管理机制
7:有一个特殊的虚拟机进程Zygote,他是虚拟机实例的孵化器。它在系统启动的时候就会产生,它会完成虚拟机的初始化,库的加载,预制类库和初始化的操作。如果系统需要一个新的虚拟机实例,它会迅速复制自身,以最快的数据提供给系统。对于一些只读的系统库,所有虚拟机实例都和Zygote共享一块内存区域。
7,listview优化
1,利用convertview回收视图,效率提高200%.
2,利用viewholder模式,效率在提高50%
3,图片处理,缓存等
1.图像尺寸不合适会导致自动缩放
2.避免实时缩放
3.最好预先缩放到视图大小
4,在性能敏感的代码里,避免创建java对象
1.测量 onmeasure()
2.布局onlayout()
3.绘图 ondraw() dispatchdraw()
4.事件处理 ontouchevent() dispatchtouchevent()
5.adapter: getview() bindview()
8,Android内存泄露
1,查询数据库而没有关闭Cursor
2,调用registerReceiver后未调用unregisterReceiver().
3,未关闭InputStream/OutputStream
4,Bitmap使用后未调用recycle()
5,Context泄露
6,集合中对象没清理造成的内存泄漏
9,HashMap与ConcurrentHashMap的区别
ConcurrentHashMap具体是怎么实现线程安全的呢,肯定不可能是每个方法加synchronized,那样就变成了HashTable。
从ConcurrentHashMap代码中可以看出,它引入了一个“分段锁”的概念,具体可以理解为把一个大的Map拆分成N个小的HashTable,根据key.hashCode()来决定把key放到哪个HashTable中。
在ConcurrentHashMap中,就是把Map分成了N个Segment,put和get的时候,都是现根据key.hashCode()算出放到哪个Segment中
以上就是ConcurrentHashMap的工作机制,通过把整个Map分为N个Segment(类似HashTable),可以提供相同的线程安全,但是效率提升N倍,默认提升16倍。最后
以上就是美丽电脑为你收集整理的android常见面试题与我自己的回答 (三)的全部内容,希望文章能够帮你解决android常见面试题与我自己的回答 (三)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复