当后台面试前端Android,你如何解决
一面(70分,毕竟不是特别帅)
信息对接,没啥好说的,仪容仪表,吐词清晰。基本都会过
但给我的感觉的话,五六个人的创业公司,Android一哥这些条件都不是我喜欢的,我自己为什么这么菜,我心里清楚,没有Android大牛和同事一起讨论,光靠自学,进步很慢,且没有竞争性,自己做的好功能,没有线下分享的空间,我内心就很不想这个公司了,既然是五六个人的创业公司,如果项目有说服力度,月入百万(人事说的),基本会找熟人,又怎么可能找我这种工作两年的小渣渣呢。
二面(20分)
渣归渣,自信还是要有的
面试问题一:Activity生命周期
7方法
onCreate —> 创建时调用
onStart —> 即将可见不可交互时调用
onResume —> 可见可交互时调用
onPause —> 即将暂停时调用
onStop —> 即将停止不可见时调用
onDestroy —> 即将销毁时调用
onRestart —> 重启时调用
正常的生命周期方法调用情况
1.长按home键再次回到 Activity 的生命周期log日志。
onRestart_A —> 重启时调用
onStart_A —> 即将可见不可交互时调用
onResume_A —> 可见可交互时调用
2.正常进入Activity_A,启动另一个Activity_B 的生命周期log日志。
onCreate_A —> 创建时调用
onStart_A —> 即将可见不可交互时调用
onResume_A —> 可见可交互时调用
onPause_A —> 即将暂停时调用
onCreate_B —> 创建时调用
onStart_B —> 即将可见不可交互时调用
onResume_B —> 可见可交互时调用
onStop_A —> 即将停止不可见时调用
3.按下物理返回键再次回到Activity_A的生命周期log日志。
onPause_B —> 即将暂停时调用
onRestart_A —> 重启时调用
onStart_A —> 即将可见不可交互时调用
onResume_A —> 可见可交互时调用
onStop_B —> 即将停止不可见时调用
onDestroy_B —> 即将销毁时调用
异常的生命周期方法调用情况
onSaveInstanceState方法和onRestoreInstanceState
当targetSdkVersion小于3时onSaveInstanceState是在onPause方法中调用的,而大于3时是在onStop方法中调用的。
而onRestoreInstanceState是在onStart之后、onResume之前调用的。
总结
6+1+2,生命周期为什么要这样设计
onPause不在第二个生命周期执行到onResume之后再执行呢?
如果这样执行的话两个Activity都 执行到onResume时候,比如你在打电话,但是你的视频仍然在播放,这就带来了很多困扰
面试问题二:IntentService与Service的区别
1.Service不属于线程进程,不适合写耗时操作,容易ANR(点击5,广播前10后60,服务前20后200,内容10)
2.IntentService是继承Service的,它和service不同的是会在onCreate中内部开了一个线程,去你执行你的耗时操作
3.IntentService在执行onCreate的方法的时候,其实开了一个线程HandlerThread,并获得了当前线程队列管理的looper,并且在onStart的时候,把消息置入了消息队列
总结
IntentService是通过Handler looper message的方式实现了一个多线程的操作,同时耗时操作也可以被这个线程管理和执行,同时不会产生ANR的情况。
面试问题三:自定义View
5中方式
- 自定义组合控件 多个控件组合成为一个新的控件,方便多处复用
- 继承系统View控件 继承自TextView等系统控件,在系统控件的基础功能上进行扩展
- 继承View 不复用系统控件逻辑,继承View进行功能定义
- 继承系统ViewGroup 继承自LinearLayout等系统控件,在系统控件的基础功能上进行扩展
- 继承ViewViewGroup 不复用系统控件逻辑,继承ViewGroup进行功能定义
绘制流程三方法
- measure() 测量View的宽高
measure(),setMeasuredDimension(),onMeasure() - layout() 计算当前View以及子View的位置
layout(),onLayout(),setFrame() - draw() 视图的绘制工作
draw(),onDraw()
Android坐标系(X→,y↓)原点在屏幕的左上角
View获取自身高度
width = getRight() - getLeft();//或者getWidth();
height = getBottom() - getTop();//或者getHeight();
View自身的坐标
通过如下方法可以获取View到其父控件的距离。
getTop();获取View到其父布局顶边的距离。
getLeft();获取View到其父布局左边的距离。
getBottom();获取View到其父布局顶边的距离。
getRight();获取View到其父布局左边的距离。
实现其构造函数
自定义属性
编写values/attrs.xml,在其中编写styleable等标签元素
在布局文件中View使用自定义的属性
在View的构造方法中通过TypedArray获取
面试问题四:Android事件分发
1.找父类的dispatchTouchEvent()
2.setOnTouchListener中onTouch方法里返回决定是否执行onTouchEvent分发
3.onTouch方法里返回false,就会再去执行onTouchEvent(event)
4.onTouch返回true,onClick就不会再执行了
5.onClick的调用情况取决于switch MotionEvent.ACTION_UPcase中的performClick方法中的
mOnClickListener 是不是为空
6.MotionEvent,false断后(局限button)
面试问题5:JVM (不全主Android和内存泄漏问题)
jvm内存模型
1.类加载
2.运行期数据区
3.执行引擎
4.本地方法库
5.本地方法接口
类的生命周期
加载、链接、初始化、使用、卸载
运行时数据区域
程序计数器,栈,堆,方法区和本地方法区
程序计数器是java虚拟机规范中唯一没有规定内存溢出情况的数据区域,因为
Java的程序计数器是用来指向下一条要执行的指令的位置,所以他是一个可预见大小的值,没有必要outOfMemory,处于cpu上无法操作
重点,java堆,简称gc主战场
1.Java堆属于线程共享区域,所有的线程共享这一块内存区域
2.从内存回收角度,Java堆可被分为新生代和老年代,这样分能够更快的回收内存
3.从内存分配角度,Java堆可划分出线程私有的分配缓存区(Thread Local AllocationBuffer,TLAB),这样能够更快的分配内存
4.当Java虚拟机动态扩展到无法申请足够内存时会抛出OutOfMemory的错误
jvm内存分配小结
1.局部变量中的基本数据类型的值直接存栈中
2.局部变量中的引用数据类型在栈中存的是引用类型的指针(地址)
3.栈中的数据与堆中的数据内存回收并不是同步的,栈中的只要方法运行完,就会直接销毁局部变量,但堆中的对象不一定立即销毁
4.类的成员变量在不同对象中各不相同,都有自己的存储空间(成员变量在堆中的对象中)。而类的方法却是该类的所有对象共享的,只有一套,对象使用方法的时候方法才被压入栈,方法不使用则不占用内存
垃圾回收机制
1.什么时候进行垃圾回收?
2.如何进行垃圾回收?
3.GC算法