Android 面试(一)

一、前言:

我主要是根据以前的工作以及很多网友的面试经验,综合整理而来,若有不足,也请大家一起指出,从来没想过危险离自己如此之近,既然来了,我们要有战胜的勇气和决心。失败并不可怕,可怕的是你再也没有站起来的决心!

二、BAT面试题:

1. 谈谈对kotlin的理解

特点:

  1. 代码量少且代码末尾没有分号;
  2. 空类型安全(编译期处理了各种null情况,避免执行时异常);
  3. 函数式的,可使用lambda表达式;
  4. 可扩展方法(可扩展任意类的的属性);
  5. 互操作性强,可以在一个项目中使用kotlin和java两种语言混合开发;
2. 要做一个尽可能流畅的ListView,你平时在工作中如何进行优化的
  1. Item布局,层级越少越好,使用hierarchyview工具查看优化。
  2. 复用convertView
  3. 使用ViewHolder
  4. item中有图片时,异步加载
  5. 快速滑动时,不加载图片
  6. item中有图片时,应对图片进行适当压缩
  7. 实现数据的分页加载
3. 对于Android 的安全问题,你知道多少
  1. 错误导出组件
  2. 参数校验不严
  3. WebView引入各种安全问题,webview中的js注入
  4. 不混淆、不防二次打包
  5. 明文存储关键信息
  6. 错误使用HTTPS
  7. 山寨加密方法
  8. 滥用权限、内存泄露、使用debug签名
4. 如何缩减APK包大小?
  1. 代码
  • 保持良好的编程习惯,不要重复或者不用的代码,谨慎添加libs,移除使用不到的libs。
  • 使用proguard混淆代码,它会对不用的代码做优化,并且混淆后也能够减少安装包的大小。
  • native code的部分,大多数情况下只需要支持armabi与x86的架构即可。如果非必须,可以考虑拿掉x86的部分。
  1. 资源
  • 使用Lint工具查找没有使用到的资源。去除不使用的图片,String,XML等等。 assets目录下的资源请确保没有用不上的文件。
  • 生成APK的时候,aapt工具本身会对png做优化,但是在此之前还可以使用其他工具如tinypng对图片进行进一步的压缩预处理。
  • jpeg还是png,根据需要做选择,在某些时候jpeg可以减少图片的体积。 对于9.png的图片,可拉伸区域尽量切小,另外可以通过使用9.png拉伸达到大图效果的时候尽量不要使用整张大图。
  1. 策略
  • 有选择性的提供hdpi,xhdpi,xxhdpi的图片资源。建议优先提供xhdpi的图片,对于mdpi,ldpi与xxxhdpi根据需要提供有差异的部分即可。
  • 尽可能的重用已有的图片资源。例如对称的图片,只需要提供一张,另外一张图片可以通过代码旋转的方式实现。
  • 能用代码绘制实现的功能,尽量不要使用大量的图片。例如减少使用多张图片组成animate-list的AnimationDrawable,这种方式提供了多张图片很占空间
5. Android与服务器交互的方式中的对称加密和非对称加密是什么?
  • 对称加密,就是加密和解密数据都是使用同一个key,这方面的算法有DES。
  • 非对称加密,加密和解密是使用不同的key。发送数据之前要先和服务端约定生成公钥和私钥,使用公钥加密的数据可以用私钥解密,反之。这方面的算法有RSA。ssh 和 ssl都是典型的非对称加密。
6. 设备横竖屏切换的时候,接下来会发生什么?
  1. 不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次

  2. 设置Activity的android:configChanges=”orientation”时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次

  3. 设置Activity的android:configChanges=”orientation|keyboardHidden”时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法

7. Android启动Service的两种方式是什么? 它们的适用情况是什么?

如果后台服务开始后基本可以独立运行的话,可以用startService。音乐播放器就可以这样用。它们会一直运行直到你调用 stopSelf或者stopService。你可以通过发送Intent或者接收Intent来与正在运行的后台服务通信,但大部分时间,你只是启动服务并让它独立运行。如果你需要与后台服务通过一个持续的连接来比较频繁地通信,建议使用bind()。比如你需要定位服务不停地把更新后的地理位置传给UI。Binder比Intent开发起来复杂一些,但如果真的需要,你也只能使用它。

  • startService:生命周期与调用者不同。启动后若调用者未调用stopService而直接退出,Service仍会运行

  • bindService:生命周期与调用者绑定,调用者一旦退出,Service就会调用unBind->onDestroy

8. 谈谈你对Android中Context的理解?

Context:包含上下文信息(外部值) 的一个参数. Android 中的 Context 分三种,Application Context ,Activity Context ,Service Context.

它描述的是一个应用程序环境的信息,通过它我们可以获取应用程序的资源和类,也包括一些应用级别操作,例如:启动一个Activity,发送广播,接受Intent信息等

9. Service的onCreate回调在UI线程中吗?

Service生命周期的各个回调和其他的应用组件一样,是跑在主线程中,会影响到你的UI操作或者阻塞主线程中的其他事情

10. 请介绍下AsyncTask的内部实现,适用的场景是?

AsyncTask内部也是Handler机制来完成的,只不过Android提供了执行框架来提供线程池来执行相应地任务,因为线程池的大小问题,所以AsyncTask只应该用来执行耗时时间较短的任务,比如HTTP请求,大规模的下载和数据库的更改不适用于AsyncTask,因为会导致线程池堵塞,没有线程来执行其他的任务,导致的情形是会发生AsyncTask根本执行不了的问题。

11. 谈谈你对binder机制的理解?
  • binder是一种IPC机制,进程间通讯的一种工具.
  • Java层可以利用aidl工具来实现相应的接口.
12. Android中进程间通信有哪些实现方式?

Intent,Binder(AIDL),Messenger,BroadcastReceiver

13. 介绍下实现一个自定义view的基本流程
  1. 自定义View的属性 编写attr.xml文件
  2. 在layout布局文件中引用,同时引用命名空间
  3. 在View的构造方法中获得我们自定义的属性 ,在自定义控件中进行读取(构造方法拿到attr.xml文件值)
  4. 重写onMesure
  5. 重写onDraw
14. Android中touch事件的传递机制是怎样的?
  1. Touch事件传递的相关API有dispatchTouchEvent、onTouchEvent、onInterceptTouchEvent
  2. Touch事件相关的类有View、ViewGroup、Activity
  3. Touch事件会被封装成MotionEvent对象,该对象封装了手势按下、移动、松开等动作
  4. Touch事件通常从Activity#dispatchTouchEvent发出,只要没有被消费,会一直往下传递,到最底层的View。
  5. 如果Touch事件传递到的每个View都不消费事件,那么Touch事件会反向向上传递,最终交由Activity#onTouchEvent处理.
  6. onInterceptTouchEvent为ViewGroup特有,可以拦截事件.
  7. Down事件到来时,如果一个View没有消费该事件,那么后续的MOVE/UP事件都不会再给它
15. Android多线程的实现方式有哪些?
  • Thread & AsyncTask
  • Thread 可以与Loop 和 Handler 共用建立消息处理队列
  • AsyncTask 可以作为线程池并行处理多任务
16. Android开发中何时使用多进程?使用多进程的好处是什么?

要想知道如何使用多进程,先要知道Android里的多进程概念。一般情况下,一个应用程序就是一个进程,这个进程名称就是应用程序包名。我们知道进程是系统分配资源和调度的基本单位,所以每个进程都有自己独立的资源和内存空间,别的进程是不能任意访问其他进程的内存和资源的。

那如何让自己的应用拥有多个进程?

很简单,我们的四大组件在AndroidManifest文件中注册的时候,有个属性是android:process,

  1. 这里可以指定组件的所处的进程。默认就是应用的主进程。指定为别的进程之后,系统在启动这个组件的时候,就先创建(如果还没创建的话)这个进程,然后再创建该组件。你可以重载Application类的onCreate方法,打印出它的进程名称,就可以清楚的看见了。再设置android:process属性时候,有个地方需要注意:如果是android:process=”:deamon”,以:开头的名字,则表示这是一个应用程序的私有进程,否则它是一个全局进程。私有进程的进程名称是会在冒号前自动加上包名,而全局进程则不会。一般我们都是有私有进程,很少使用全局进程。他们的具体区别不知道有没有谁能补充一下。

  2. 使用多进程显而易见的好处就是分担主进程的内存压力。我们的应用越做越大,内存越来越多,将一些独立的组件放到不同的进程,它就不占用主进程的内存空间了。当然还有其他好处,有心人会发现Android后台进程里有很多应用是多个进程的,因为它们要常驻后台,特别是即时通讯或者社交应用,不过现在多进程已经被用烂了。典型用法是在启动一个不可见的轻量级私有进程,在后台收发消息,或者做一些耗时的事情,或者开机启动这个进程,然后做监听等。还有就是防止主进程被杀守护进程,守护进程和主进程之间相互监视,有一方被杀就重新启动它。应该还有还有其他好处,这里就不多说了。

  3. 坏处的话,多占用了系统的空间,大家都这么用的话系统内存很容易占满而导致卡顿。消耗用户的电量。应用程序架构会变复杂,应为要处理多进程之间的通信。这里又是另外一个问题了。

17. ANR是什么?怎样避免和解决ANR?

ANR:Application Not Responding,即应用无响应

ANR一般有三种类型:

1:KeyDispatchTimeout(5 seconds) –主要类型

按键或触摸事件在特定时间内无响应

2:BroadcastTimeout(10 seconds)

BroadcastReceiver在特定时间内无法处理完成

3:ServiceTimeout(20 seconds) –小概率类型

Service在特定的时间内无法处理完成

超时的原因一般有两种:

(1)当前的事件没有机会得到处理(UI线程正在处理前一个事件没有及时完成或者looper被某种原因阻塞住)

(2)当前的事件正在处理,但没有及时完成

UI线程尽量只做跟UI相关的工作,耗时的工作(数据库操作,I/O,连接网络或者其他可能阻碍UI线程的操作)放入单独的线程处理,尽量用Handler来处理UI thread和thread之间的交互。

UI线程主要包括如下:

Activity:onCreate(), onResume(), onDestroy(), onKeyDown(), onClick()

AsyncTask: onPreExecute(), onProgressUpdate(), onPostExecute(), onCancel()

Mainthread handler: handleMessage(), post(runnable r)

18. Android下解决滑动冲突的常见思路是什么?

相关的滑动组件 重写onInterceptTouchEvent,然后判断根据xy值,来决定是否要拦截当前操作

19. 如何把一个应用设置为系统应用?
  • 成为系统应用,首先要在 对应设备的 Android 源码 SDK 下编译,编译好之后:

  • 此 Android 设备是 Debug 版本,并且已经 root,直接将此 apk 用 adb 工具 push 到 system/app 或 system/priv-app 下即可。

  • 如果非 root 设备,需要编译后重新烧写设备镜像即可。

  • 有些权限(如 WRITE_SECURE_SETTINGS ),是不开放给第三方应用的,只能在对应设备源码中编译然后作为系统 app 使用。

20. Android内存泄露研究

Android内存泄漏指的是进程中某些对象(垃圾对象)已经没有使用价值了,但是它们却可以直接或间接地引用到gc roots导致无法被GC回收。无用的对象占据着内存空间,使得实际可使用内存变小,形象地说法就是内存泄漏了。

场景

  • 类的静态变量持有大数据对象

  • 静态变量长期维持到大数据对象的引用,阻止垃圾回收。

  • 非静态内部类的静态实例

  • 非静态内部类会维持一个到外部类实例的引用,如果非静态内部类的实例是静态的,就会间接长期维持着外部类的引用,阻止被回收掉。

  • 资源对象未关闭

  • 资源性对象如Cursor、File、Socket,应该在使用后及时关闭。未在finally中关闭,会导致异常情况下资源对象未被释放的隐患。

  • 注册对象未反注册

  • 未反注册会导致观察者列表里维持着对象的引用,阻止垃圾回收。

  • Handler临时性内存泄露

Handler通过发送Message与主线程交互,Message发出之后是存储在MessageQueue中的,有些Message也不是马上就被处理的。在Message中存在一个 target,是Handler的一个引用,如果Message在Queue中存在的时间越长,就会导致Handler无法被回收。如果Handler是非静态的,则会导致Activity或者Service不会被回收。

  • 由于AsyncTask内部也是Handler机制,同样存在内存泄漏的风险。
    此种内存泄露,一般是临时性的。
21. 内存泄露检测有什么好方法?

检测:

1、DDMS Heap发现内存泄露

dataObject totalSize的大小,是否稳定在一个范围内,如果操作程序,不断增加,说明内存泄露

2、使用Heap Tool进行内存快照前后对比

BlankActivity手动触发GC进行前后对比,对象是否被及时回收

定位:

1、MAT插件打开.hprof具体定位内存泄露:

查看histogram项,选中某一个对象,查看它的GC引用链,因为存在GC引用链的,说明无法回收

2、AndroidStudio的Allocation Tracker:

观测到期间的内存分配,哪些对象被创建,什么时候创建,从而准确定位

三、小细节:

1. 如何通过广播拦截和abort一条短信?
2. 广播是否可以请求网络?
3. 广播引起anr的时间限制是多少?
4. Android线程有没有上限?
5. Android为什么引入Parcelable?
6. 有没有尝试简化Parcelable的使用?
7. RxJava:在使用RxJava时,如果在发布了一个订阅后,由于没有及时取消,导致Activity/Fragment无法销毁,导致的内存泄露。

解决办法:使用RxLifeCycle

8. 两个Activity 之间跳转时必然会执行的是哪几个方法?

前一个Activity的onPause,后一个Activity的onResume

9. 前台切换到后台,然后再回到前台,Activity生命周期回调方法。弹出Dialog,生命值周期回调方法。

1)前台切换到后台,会执行onPause->onStop,再回到前台,会执行onRestart->onStart->onResume

  1. 弹出Dialog,并不会影响Activity生命周期
10. Application 和 Activity 的 Context 对象的区别

1)Application Context是伴随应用生命周期;不可以showDialog, startActivity, LayoutInflation

可以startService\BindService\sendBroadcast\registerBroadcast\load Resource values

2)Activity Context指生命周期只与当前Activity有关,而Activity Context这些操作都可以,即凡是跟UI相关的,都得用Activity做为Context来处理。

一个应用Context的数量=Activity数量+Service数量+1(Application数量)

11. 说说你对Java反射的理解

JAVA反射机制是在运行状态中, 对于任意一个类, 都能够知道这个类的所有属性和方法; 对于任意一个对象, 都能够调用它的任意一个方法和属性。 从对象出发,通过反射(Class类)可以取得取得类的完整信息(类名 Class类型,所在包、具有的所有方法 Method[]类型、某个方法的完整信息(包括修饰符、返回值类型、异常、参数类型)、所有属性 Field[]、某个属性的完整信息、构造器 Constructors),调用类的属性或方法自己的总结: 在运行过程中获得类、对象、方法的所有信息。

12. 开启线程的三种方式?

有三种创建线程的方式,分别是继承Thread类、实现Runable接口和使用线程池

13. synchronized 和volatile 关键字的区别
  1. volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
  2. volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的
  3. volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性
  4. volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
  5. volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化
14. mvc 和 mvp mvvm
  1. mvc:数据、View、Activity,View将操作反馈给Activity,Activitiy去获取数据,数据通过观察者模式刷新给View。循环依赖
  • Activity重,很难单元测试
  • View和Model耦合严重
  1. mvp:数据、View、Presenter,View将操作给Presenter,Presenter去获取数据,数据获取好了返回给Presenter,Presenter去刷新View。PV,PM双向依赖
  • 接口爆炸
  • Presenter很重
  1. mvvm:数据、View、ViewModel,View将操作给ViewModel,ViewModel去获取数据,数据和界面绑定了,数据更新界面更新。
  • viewModel的业务逻辑可以单独拿来测试
  • 一个view 对应一个 viewModel 业务逻辑可以分离,不会出现全能类
  • 数据和界面绑定了,不用写垃圾代码,但是复用起来不舒服
15. 屏幕适配的处理技巧都有哪些?
16. 怎么去除重复代码?
17. 动态布局的理解
20. 画出 Android 的大体架构图
21. 动态权限适配方案,权限组的概念
22. 下拉状态栏是不是影响activity的生命周期
23. android中开启摄像头的主要步骤
24. 点击事件被拦截,但是想传到下面的View,如何操作?
25. 微信主页面的实现方式
26. 微信上消息小红点的原理

四、混合开发面试

1. Hybrid做过吗?
2. Hybrid通信原理是什么,有做研究吗?
3. react native有多少了解?讲一下原理。
4. weex了解吗?如何自己实现类似技术?
5. flutter了解吗?内部是如何实现跨平台的?
6. Dart语言有研究贵吗?
7. 快应用了解吗?跟其她方式相比有什么优缺点?
8. 说说你用过的混合开发技术有哪些?各有什么优缺点?
9. groovy语法会吗?
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值