1.自我介绍。(我去,完全没准备,很久之前准备的全部忘了~)
2.android如何处理OOM?
出现OOM的原因主要有两大类:一、加载对象过大;二、相应资源过多,来不及释放。
如何处理OOM:
1、在对象引用上做处理,比如软引用、弱引用和虚引用。 详情点击。
在过去,我们经常会使用一种非常流行的内存缓存技术的实现,即软引用或弱引用 (SoftReference or WeakReference)。但是现在已经不再推荐使用这种方式了,因为从 Android 2.3 (API Level 9)开始,垃圾回收器会更倾向于回收持有软引用或弱引用的对象,这让软引用和弱引用变得不再可靠。另外,Android 3.0 (API Level 11)中,图片的数据会存储在本地的内存当中,因而无法用一种可预见的方式将其释放,这就有潜在的风险造成应用程序的内存溢出并崩溃。
2、在内存中加载图片时直接在内存中做处理,比如:边界压缩。
2.1、多数情况下OOM是因为bitmap太大,所以在bitmap加载到内存是需要进行压缩处理的。
有两种压缩方式,第一种通过BitmapFactory.decodeFile(path,option)对图片按比例进行压缩,读到内存中是压缩过的图片大小,但图片质量会受到影响;第二种是通过image.compress(Bitmap.CompressFormat.JPEG, 100, baos)
来对图片进行质量压缩,也就是图片质量不受影响,但需要把原bitmap整个读入到内存中。一般来说,第一种方法是肯定要使用的,如果需要把bitmap通过网络上传到服务器端,则在使用完第一种方式后再用第二种方式进行压缩,
来减少流量损失。
2.2、所以需要主动释放Bitmap的内存;
bitmap.recycle();
2.3、最好是设计Cache,利用android提供的LruCache机制,用内存的一部分作为缓存。
3、动态回收内存。
4、优化Dalvik虚拟机的堆内存分配。
5、自定义堆内存大小。
3.listView如何优化?
listView加载数据都是在其适配器,比如继承了BaseAdapter、SimpleAdapter和CursorAdapter的适配器的View getView(int position,View contentView,ViewGroup parent)方法中实现的。
1、用convertView缓存,不需要每次都重新创建一个view对象;
2、定义一个static的成员内部类viewHolder,在contentView上绑定这个viewHolder,不需要每次都findviewbyId;
3、对于加载大数据量的网络数据,需要进行分页加载,超过最大数量则覆盖,否则容易出现OOM,通过adapter.notifyDataSetChanged()方法更新listView。
4、关于加载网络图片,最好用缓存框架,比如LruCache,防止来回拉动listview时,重复进行图片下载操作。
http://www.devba.com/index.php/archives/5966.html
http://blog.csdn.net/jacman/article/details/7087995
4.jpg和PNG的区别?(额,这个真心不知道。。。)
简单地说,PNG是无损压缩的图片格式,而JPG是有损压缩的图片格式。
因此虽然同样大小的两张图片,PNG的存储大小明显比JPG的要大很多。
5.堆和栈的区别?
JVM运行时内存区,有两类栈和一个堆。
两个栈分别为虚拟机栈和本地方法栈
首先说下虚拟机栈的用途,一个线程的每个方法在执行的同时都会创建一个栈帧,栈帧中存储的有局部变量表、操作站、动态链接、方法出口等,当方法调用时,
栈帧入栈,在方法完成时,栈帧出栈。每个线程对应着一个虚拟机栈,所以虚拟机栈是线程私有的。
本地方法栈和虚拟机栈差不多,唯一的区别是:虚拟机栈是执行Java方法的,而本地方法栈是用来执行native方法的。
堆:在JVM内存管理中,堆是内存最大的一块,是线程共享的内存区域,用来存放对象实例。其分配和回收机制为分代分配、分代回收。
6.String的存储形式?
String的存储形式是char类型数组,然后又提到new和直接赋值两种方式,也讲到了常量池。。。
String str1="ABC" 可能创建一个对象或者不创建对象,如果"ABC"这个字符串在java String池里不存在,会在java String池创建这个一个String对象("ABC").如果已经存在,str1直接reference to 这个String池里的对象。
String str2 = new String("ABC") 至少创建一个对象,也可能两个。因为用到new 关键字,会在heap创建一个 str2 的String 对象,它的value 是 "ABC".同时,如果"ABC"这个字符串在java String池里不存在,会在java String池创建这个一个String对象("ABC").
常量池是在JAVA内存区中的方法区中。
8.问是否可以改变String的内容?
不可以在原对象上改变String的内容,因为其内部的char型数组是final关键词修饰的。但可以通过StringBuffer和StringBuilder这两个类动态修改和扩充String的内容,只是需要重新创建一个String对象,即原对象的String内容仍然没有任何改变。
9.是否熟悉android的ClassLoader?
Dalvik虚拟机不是一般的java虚拟机,所以类加载机制和java虚拟机有相似之处,也有不同之处。
相似之处是双亲委派机制,不同之处是动态类加载机制。
在Dalvik虚拟机里,ClassLoader不好使,我们如何实现动态类加载机制呢?Android为我们从ClassLoader派生出两个子类,DexClassLoader和PathClassLoader,
这两个类都是通过DexFile类实现加载的,加载的类文件是dex文件或者包含有dex文件的.apk文件或者.jar文件。
8.听到我说熟悉javaClassLoader,立马让我解释java的双亲委派机制。
之前有总结过~
9.看到我项目有个涉及到了数据库,接下来问了一堆数据库的问题(尼玛,no zuo no die啊,这是我的弱项),什么如何提高数据库查询速度?如何优化sql语句?分组查询语句?
1、提高查询速度,用索引;
2、优化sql语句:1、不要滥用select * ,查找几列就写几个属性;2、!= null 最好改为!=0;3、in{1,2,3} 改为 between 1 and 3;4、where id =1 or id=2 改为用union,select * from emp where id =1 union (select * from emp where id=2)。
3、分组查询:group by。
group by 从英文里理解就是分组。必须有“聚合函数”来配合才能使用,使用时至少需要一个分组标志字段。
什么是“聚合函数”?
像sum()、count()、avg()等都是“聚合函数”
使用group by 的目的就是要将数据分类汇总。关于group by的解析。
10.hashtable和hashmap区别?多线程下如何使用hashmap?hash原理,时间复杂度?线程和进程区别?线程的生命周期?
1、三个区别:实现的接口不一样,hashTable实现的是Dictionary接口,hashmap实现的是map接口;hashTable不允许数据的key为null,而hashmap允许;
hashtbale是线程安全的,hashmap是线程非安全的,需要处理同步问题。
2、需要处理线程同步问题,对于共享对象,不同对象互斥地访问,具体通过synchronized实现。
3、“拉链法”,查询的时间复杂度为O(1), 两种遍历的方式的时间复杂度分别为O(n)和O(n^2)。
4、进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,它是系统进行资源分配和调度的一个独立单位,一个进程内部可以包含多个线程。线程是CPU进行分派和调度的最小单位,多个线程可以共享同一个进程
的资源,一个线程运行只需要很少的资源(程序计数器、一组寄存器和栈)。
5、线程的生命周期。
11.然后情况直转而下。。。。java的锁有哪几种?(多线程这块我还没复习到啊我想说。。。。)lock和synchronized区别?。。。
java锁:有两种,一种是synchronized,一种是lock。
两者的区别是:synchronized是在JVM层面实现的,因此系统可以监控锁的释放与否,而ReentrantLock使用代码实现的,系统无法自动释放,需要在代码中finally子句中显式释放锁lock.unlock()。
在并发量小的情况下,使用synchronized是个不错的选择,但是在并发量比较高的情况下,其性能下降很严重,此时ReentrantLock是个不错的方案。
12.面试官看我答的不太好(我估计是。。说话有点抖。。),不问线程了,开始问java io,让我举几个io类,我貌似一口气说了一堆哈哈~
当然没这么简单,接着问我是否熟悉NIO,哎,不熟悉啊,只说了这个NIO是个new io也是个not block io,然后就没然后了。。。
IO类分类字符流和字节流,字符流有两个抽象类Reader和Writer,其对应子类FileReader和FileWriter可实现文件的读写操作,BufferedWriter和BufferedReader能够提供缓冲区功能,用以提高效率;字节流也有两个抽象类InputStream和OutputStream,其对应子类FileInputStream和OutputStream可实现对文件的读写操作,BufferedInputStream和BufferedOutputStream能够提供缓冲区功能,用以提高效率。
什么时候用字符流什么时候用字节流?字符流适合操作带有字符的文件的场合,字节流适合操作无法直接获取字符的二进制文件,比如图片、mp3、视频文件等等。
NIO:详情点击。
13.java到这就问完了,接下来问了一堆android相关的,比如子线程和ui通信的方式,service通信的方式及工作原理?handler机制?touch传递机制?
1、子线程和UI通信的方式:
一个线程拥有一个Message Queue,对应有一个Looper负责管理和运转该Message Queue,UI线程(即主线程)的handler将一个Message(Massage中包含了消息ID,消息处理对象以及处理的数据)push到子线程的Message Queue中,Message Queue中的Message先进先出,当Looper从Message Queue中抽取一个Message出队列,handler就负责处理该Message。通过这种方式子线程就可以和UI线程通信。
2、service通信的方式及工作原理:
service和Activity进行通信,我所知道的有两种方式,一种是service通过IBinder和Activity通信;第二种是service通过BroadCast Receiver和Activity通信。
3、handler机制:
一个线程拥有一个Message Queue,对应有一个Looper负责管理和运转该Message Queue,UI线程(即主线程)的handler将一个Message(Massage中包含了消息ID,消息处理对象以及处理的数据)push到子线程的Message Queue中,Message Queue中的Message先进先出,当Looper从Message Queue中抽取一个Message出队列,handler就负责处理该Message。通过这种方式子线程就可以和UI线程通信。
4、touch传递机制:
每一个继承自ViewGroup的子类都有以下三个和TouchEvent联系非常紧密的方法:
(1)public boolean dispatchTouchEvent(MotionEvent ev);//转发TouchEvent
(2) public boolean onInterceptTouchEvent(MotionEvent ev);//拦截TouchEvent
(3) public boolean OnTouchEvent(MotionEvent ev);//处理TouchEvent
而View的子类只有OnTouchEvent方法;
14.我们都知道,activity有一个生命周期。。。(哈哈,难道让我说activity的生命周期嘛?)。。那你说说android为什么要设计一个生命周期呢??
额,,,,这还真没考虑过。。(更好的控制程序逻辑?更好地操作数据?更好地管理界面??该怎么答?谁能告诉我?)。。
运用模板方法的设计模式,父类activity生命周期中的逻辑实现由其子类完成,实现"好莱坞法则":"Don't call me,i will call you."。
15.activity的生命周期是由谁控制的??
ActivityManagerService,属于Android 框架层。
16.下面是算法部分:(哎,准备的东西一点也没问到。。。)
链表和数组的区别?二分查找算法?
二分查找有两种实现方式:递归和非递归(循环),后者效率比前者高。 点击详情。
如何进一步提高二分查找的效率?(这个有谁知道???)
二分查找和跳跃表的区别??(我去。。跳跃表没看。。。)
下面都是非技术问题了:
17.以后希望在哪工作?(南京、无锡、杭州。。嘿嘿~)
18.如何学android的?(自学。。)
19.是否有关注过大牛的博客?
20.如何去阅读大牛博客,是否会自己思考?
18.面试到此结束,问我有啥问题没?
我当然说有啊,我问了他是咋学android的,他回答说:看源码!
总结:
总体来说,回答的不咋地,一是紧张,二是还没准备好,三是我太菜!!!!
通过这次电话面试,我的感觉是:
1.还要提高自身的表达能力!
2.充分准备真的很有必要!
3.不要紧张!
技术上面还需提高的有:
1.NIO、2.java并发、3.android设计原理、4.数据库 5.数据结构与算法