Android技术面试Android部分

一、基础知识

1.Android启动模式

针对android的启动模式,需要了解下Activity栈和taskAffinity等知识。

Standard:系统默认,启动一个就多一个Activity实例

SingleTop:栈顶复用,如果处于栈顶,则生命周期不走onCreate()和onStart(),会调用onNewIntent(),适合推送消息详情页,比如新闻推送详情Activity;

SingleTask:栈内复用,如果存在栈内,则在其上所有Activity全部出栈,使得其位于栈顶,生命周期和SingleTop一样,app首页基本是用这个

SingleInstance:这个是SingleTask加强本,系统会为要启动的Activity单独开一个栈,这个栈里只有它,适用新开Activity和app能独立开的,如系统闹钟。

Intent也需要进一步了解,Action、Data、Category各自的用法和作用,还有常用的

Intent.FLAG_ACTIVITY_SINGLE_TOP

Intent.FLAG_ACTIVITY_NEW_TASK

Intent.FLAG_ACTIVITY_CLEAR_TOP

2.View的绘制流程

ViewRoot 
-> performTraversal()
-> performMeasure()
-> performLayout()
-> perfromDraw()
-> View/ViewGroup measure()
-> View/ViewGroup onMeasure()
-> View/ViewGroup layout()
-> View/ViewGroup onLayout()
-> View/ViewGroup draw()

针对View的绘制,还需要了解invalidate方法和requestLayout方法。

invalidate方法,有带4个参数的,和不带参数有什么区别?

requestLayout触发measure和layout,如何实现局部重新测量,避免全局重新测量问题?

3.事件分发机制

-> dispatchTouchEvent()
-> onInterceptTouchEvent()
-> onTouchEvent()
requestDisallowInterceptTouchEvent(boolean)

另外还有onTouchEvent()、onTouchListener、onClickListener的先后顺序等问题。

4.消息分发机制(Handler/Looper机制)

(1).为什么一个线程只有一个Looper、只有一个MessageQueue?

(2).如何获取当前线程的Looper?是怎么实现的?(理解ThreadLocal)

(3).是不是任何线程都可以实例化Handler?有没有什么约束条件?

(4).Looper.loop是一个死循环,拿不到需要处理的Message就会阻塞,那在UI线程中为什么不会导致ANR?

(5).Handler.sendMessageDelayed()怎么实现延迟的?结合Looper.loop()循环中,Message=messageQueue.next()和MessageQueue.enqueueMessage()分析。

5.如何保证Service不被杀死?如何保证进程不被杀死?

答:开启2个Service相互监听,如果有一方被kill掉,另一个捕获到立即启动,以达到service永远都在运行的状态。

6.Android的进程通信机制(Binder/IPC)? 线程(进程间)通信机制有哪些?

答:略。

7.SharedPreference原理?能否跨进程?如何实现?

答:略。

8.bundle的数据结构,如何存储,既然有了Intent.putExtra,为啥还要用bundle。

答:bundle的内部结构其实是Map,传递的数据可以是boolean、byte、int、long、float、double、string等基本类型或它们对应的数组,也可以是对象或对象数组。当Bundle传递的是对象或对象数组时,必须实现Serializable 或Parcelable接口。

9.asynctask的原理

答:AsyncTask是对Thread和Handler的组合包装。

二、性能优化

1.UI优化

(1)合理地选择RelativeLayout /LinearLayout/FrameLayout。

RelativeLayout会让子View调用2次onMeasure,而且布局相对复杂时,onMeasure相对比较复杂,效率比较低,LinearLayout在weight > 0时也会让子View调用2次onMeasure。

(2)合理地使用<include> <merge> <ViewStub>等布局标签。

(3)减少布局层级,可以通过手机开发者选项 GPU过渡绘制查看,一般控制在4层以内,超过5层就要考虑是否需要重新排版布局。

(4)自定义View时,重写onDraw()方法,不要在该方法中新建对象,否则容易触发GC,导致性能下降。

(5)使用ListView时需要复用contentView,并使用Holder减少findViewById加载View。

(6)去除不必要背景:getWindow().setBackgroundDrawable(null)。

(7)使用TextView的leftDrawable/rightDrawable代替ImageView+TextView布局。

2.内存优化

内存优化主要是为了避免OOM和频繁触发到GC导致性能下降(使用LeakCanary检测内存泄露)。

(1)尽可能的规范编码,不在使用的资源注意回收,例如:Bitmap.recycle(), Cursor.close, inputStream.close()。

(2)大量加载Bitmap时,根据View大小加载Bitmap,合理选择inSampleSize,RGB_565编码方式;以及使用LruCache缓存机制。

(3)使用 静态内部类+WeakReference 代替内部类,如Handler、线程、AsyncTask。

(4)使用线程池管理线程,避免线程的新建。

(5)使用单例持有Context,需要记得释放,或者使用全局上下文。

(6)静态集合对象注意释放。

(7)使用webView时,在Activity的onDestory方法中需要移除和销毁,webView.removeAllViews()和webView.destory() 。

3.响应速度优化

Activity如果5秒之内无法响应屏幕触碰事件和键盘输入事件,就会出现ANR;而BroadcastReceiver如果10秒之内还未执行操作也会出现ANR;Server20秒会出现ANR,为了避免ANR,可以开启子线程执行耗时操作,但是子线程不能更新UI,因此需要Handler消息机制、AsyncTask、IntentService进行线程通信。

备:出现ANR时,adb pull data/anr/tarces.txt 结合log分析。

4.其他性能优化

(1)常量使用static final修饰。

(2)使用SparseArray代替HashMap。SparseArray内部存储是通过两个数组(压缩式稀疏数组),查找是通过二分法查找。HashMap底层是一个Hash表,是数组和链表的集合实现,数据量大时查找遍历元素就会很耗内存。

(3)使用线程池管理线程。

(4)根据循环的性能对比,ArrayList遍历使用常规for循环,LinkedList使用foreach。

(5)不要过度使用枚举,枚举占用内存空间比整型大。

(6)字符串的拼接优先考虑StringBuilder和StringBuffer。

(7)数据库存储是采用批量插入+事务。

5.设计模式

单例模式、观察者模式、适配器模式、工厂模式、MVC/MVP/MVVM

6.数据结构

(1)HashMap、LinkedHashMap、ConcurrentHashMap在用法和原理上的差异。

(2)ArrayList(通过数组实现)和LinkedList(基于双向循环链表的,且头结点中不存放数据)对比,它们均实现于List接口。

(3)平衡二叉树、二叉查找树、红黑树。

(4)Set的原理(hash算法)?常用hash算法(MD4/MD5/SHA-1)?HashSet内部用到了HashMap(底层结构是哈希表)。

三、APP打包

TODO

results matching ""

    No results matching ""