经朋友推荐,昨天下午去网易杭州公司参加了考拉海淘android客户端的面试。今天回忆一下面试题目,做个整理进行备案。
1、说说JVM垃圾回收机制。
1.1、画了JVM分代回收的图,大致说了下垃圾分代回收的机制,并且说了年轻代和年老代GC的算法分别是“停止-复制”法和“标记-整理”法。
1.2、这时面试官问我年轻代中survivor0和survivor1之间的复制是如何进行的?我说当survivor0区域也满了的时候,仍然存活下来的对象直接复制到survivor1中,这个答案他并不满意,不过我也说不出具体复制的策略,所以这个问题翻篇了。
1.3、面试官又问我你觉得这三个内存区里哪几个可能会发生内存溢出?我说方法区不可能,年老代会发生内存溢出。他反问我年轻代不会发生内存溢出吗?我急忙说也会。。。其实仔细想想三个区都有可能发生内存溢出。
1.4、方法区中的static变量什么时候分配内存什么时候被回收?分配是在类加载的时候,回收是在该类的Class对象被回收了,static变量才会被回收,因为static变量始终会有一个Class 对象的句柄指向它,static变量是属于类级别的。
2、让我选自己做过的项目中的一个,问我这个项目涉及到哪些安卓相关技术?
我选了自己最有把握的一个,说涉及到的安卓相关技术有Activity.....没说完,他就让我说一下Activity的生命周期,我画了个完整的Activity生命周期图。他问我如果一个位于前台的Activity,执行finish方法,会触发哪些生命周期的方法?我说OnPause()->OnStop()->OnDestory()。然后他让我再说一下Activity的启动模式。。对于singleInstance这种启动模式我没解释清楚,其实也是没有理解。
3、遇到过ANR吗?
Android not responding。我说在主线程中进行比较耗时的操作会造成ANR,比如网络请求和数据库操作等耗时的操作,给用户一种界面假死的错觉。如何解决ANR?将耗时的操作放在子线程中执行,通过handler来实现主线程和子线程的通讯,比如对UI界面进行刷新。
4、安卓网络请求的方式?
主要有两个类来完成,一个是HttpURLConnection,另一个是HttpClient。他问我我这个项目中的网络请求是怎么实现的?我说通过开启一个子线程来完成网络请求操作,用HttpClient来执行HttpPost对象以实现http post请求,当服务器端成功返回数据后,将返回的json格式的数据封装成json类,然后用主线程的handler执行sendMessage(Message msg)方法,主线程中handler执行handleMessage(Message msg)方法对json类进行处理。另一个面试官问到handler是在哪个线程中执行的?我回答道是主线程。他又说handler可能导致内存泄漏,你如何解决?我说道可以在Activity的OnDestory()方法中加入handler.removecallbacks(Runnable Thread)来结束线程。
5、多线程并发问题,如何实现同时从服务器端下载20张图片(不用异步下载的框架,就用handler实现)?
1、第一种方法效率比较低:开启20个下载图片的线程,每个线程下载完毕后用,创建一个Message msg = handler.obtainMessage(id,bitmap)(hanlder为主线程的中定义的handler),然后handler.sendMessage(msg);主线程中handler.handleMessage(Message msg)根据msg的id,将bitmap赋予对应的imageView;
2、显然第一种方法虽然实现了线程并发,但要开启20个线程,显然占用很大的系统资源和内存,容易出现OOM。下面说一下一个带有下载功能的缓存框架的实现思路:
2.1、将url和imageView封装成一个类叫做ImageRef.
2.2、定义一个图片加载栈mImageStack,一个请求更新UI的队列mImageQueue.
2.3、下载20个图片,可以用一个循环依次将20个封装好的ImageRef对象加入到mImageStack中.
2.4、定义一个加载图片的handler,实现图片下载。
2.5、如果handler为空,则创建一个HanlderThread,并将其Looper给予handler,由handler来负责处理Looper从该线程中抽取的Message。
2.6、从mImageStack中pop一个imageRef,handler.sendMessage(new Message(id,imageRef)),handler.handleMessage(Msg)在handler线程中下载图片,下载得到bitmap后,由ui线程的handler,取名为handler2发送封装了bitmap的message.并且将用来标记图片加载线程是否可用的isLoading设置为false,表示图片加载线程不可用。
2.7、在handler2.handleMessage(Message msg)中从mImageQueue中取出对头元素imageRef,然后更新其中的mageView,并将isLoading设置为ture.
2.8、重复第6步。
6、项目中有没有自定义的view?
我说了两个,一个是首页的瀑布流效果的scrollView,是由左右两个LinearLayout实现的;还有一个是流布局FlowLayout,这个view其中有一个面试官问我是继承自哪个类的,我说是LinearLayout,他说应该是ViewGroup。回来一看还果真是ViewGroup,确实牛。。。
7、知道的设计模式有哪些?
有两类,一类是创建者模式,还有一类是结构型模式。创建者模式:多个方法工厂模式、静态方法工厂模式、抽象方法工厂模式、单例模式、原型模式;结构型模式:装饰器模式、适配器模式和代理模式。然后他问我知道观察者模式吗?这个。。。我知道在ContentProvider中的运用,并不知道其实现原理。然后起身走开,让我单独写一下观察者模式的结构。。。