安卓面试题
Posted android与kotlin以及java架构
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了安卓面试题相关的知识,希望对你有一定的参考价值。
android的四大组件,简要说明用处
Activity:Activity是Android程序与用户交互的窗口,是Android构造块中最基本的一种,它需要为保持各界面的状态,做很多持久化的事情,妥善管理生命周期以及一些跳转逻辑。
BroadCast Receiver:接受一种或者多种Intent作触发事件,接受相关消息,做一些简单处理,转换成一条Notification,统一了Android的事件广播模型。
Content Provider:是Android提供的第三方应用数据的访问方案,可以派生Content Provider类,对外提供数据,可以像数据库一样进行选择排序,屏蔽内部数据的存储细节,向外提供统一的接口模型,大大简化上层应用,对数据的整合提 供了更方便的途径。
service:后台服务于Activity,封装有一个完整的功能逻辑实现,接受上层指令,完成相关的事务,定义好需要接受的Intent提供同步和异步的接口。
Activity的生命周期(各种情况下的生命周期)
Activity生命周期方法主要有onCreate()、onStart()、onResume()、onPause()、onStop()、onDestroy()和onRestart()等7个方法。
启动一个A Activity,分别执行onCreate()、onStart()、onResume()方法。
从A Activity打开B Activity分别执行A onPause()、B onCreate()、B onStart()、B onResume()、A onStop()方法。
关闭B Activity,分别执行B onPause()、A onRestart()、A onStart()、A onResume()、B onStop()、B onDestroy()方法。
横竖屏切换A Activity,清单文件中不设置android:configChanges属性时,先销毁onPause()、onStop()、onDestroy()再重新创建onCreate()、onStart()、onResume()方法,设置orientation|screenSize(一定要同时出现)属性值时,不走生命周期方法,只会执行onConfigurationChanged()方法。
Activity之间的切换可以看出onPause()、onStop()这两个方法比较特殊,切换的时候onPause()方法不要加入太多耗时操作否则会影响体验。
fragment的生命周期(与Activity关联)
和Activity做对比
Fragment的生命周期方法主要有onAttach()、onCreate()、onCreateView()、onActivityCreated()、onstart()、onResume()、onPause()、onStop()、onDestroyView()、onDestroy()、onDetach()等11个方法。
切换到该Fragment,分别执行onAttach()、onCreate()、onCreateView()、onActivityCreated()、onstart()、onResume()方法。
锁屏,分别执行onPause()、onStop()方法。
亮屏,分别执行onstart()、onResume()方法。
覆盖,切换到其他Fragment,分别执行onPause()、onStop()、onDestroyView()方法。
从其他Fragment回到之前Fragment,分别执行onCreateView()、onActivityCreated()、onstart()、onResume()方法。
Activity的启动模式,简要说明用法
standard:每次激活Activity时都会创建Activity实例,并放入任务栈中。这个是默认的;
singleTop:如果已经存在在栈顶在对方的任务一个同类型的活动实例,不会有任何新的activity创造,而是被发送到一个存在的activity实例通过onNewIntent() 方法的意图,即会重用该实例调用当前activity的onNewIntent() 方法。适合接收通知启动的内容显示页面。
例如,某个新闻客户端的新闻内容页面,如果收到10个新闻推送,每次都打开一个新闻内容页面是很烦人的。singleTask:如果系统中有一个存在的活动实例,整个任务将实例将被移动到顶部,Intent将通过onnewintent()方法交付。否则,新的activity将被创建并放置在适当的任务中。适合作为程序入口点。
例如浏览器的主界面。不管从多少个应用启动浏览器,只会启动主界面一次,其余情况都会走onNewIntent,并且会清空主界面上面的其他页面。singleInstance适合需要与程序分离开的页面。
例如闹铃提醒,将闹铃提醒与闹铃设置分离。
singleInstance不要用于中间页面,如果用于中间页面,跳转会有问题,比如:A -> B (singleInstance) -> C,完全退出后,在此启动,首先打开的是B。
Service的生命周期以及启动方式
startService (定义一个Service的子类 清单文件注册 startService开启服务 stopService 停止服务)
特点:主要用于启动一个服务执行后台任务,不能进行通信,一旦开启就和开启这本身没有联系了,即使开启者挂了,服务照样执行
生命周期:onCreate()--》onStartCommand()(onStart()已经过时)----》onDestory()
TIP:如果服务已经开启,不会重复的执行onCreate(),而是会调用onStart和onStartCommand()方法,服务停止的时候调用OnDestory()服务只会被停止一次,
bindService(定义一个Service的子类 清单文件注册 bindService(Intent, ServiceConnection, int)绑定服务 unbindService(ServiceConnection)停止服务)
特点:理论上只可以绑定一次,bind的方式开启服务,绑定服务,调用者挂了,服务也会跟
着挂掉。绑定者可以调用服务里面的方法。
TIP:绑定服务不会调用onstart()
或者onstartcommand()
方法,
总结:Service既可以bindService又可以startService,如果绑定服务的调用者挂了,服务照样执行,除非调用stopService或者他本身stop,服务才会停止
IntentService和Service的区别,应用场景
Service是在主线程中而没有另开新的线程执行任务,不能处理耗时操作;
而IntentServicee是有替代Service处理耗时操作的作用,从IntentService的源码中我们也可以看到IntentService实际也是通过Handler来进行主线程的UI更新等操作;IntentServicee有一个抽象方法onHandleIntent,在这里可以处理耗时操作;
广播的注册方式,以及有什么不同,以及广播的作用
静态模式
清单文件中注册,Activity回收之后仍然可以接受消息,电量、屏幕亮度等
动态模式
注册的方法是registerReceiver(receiver,filter)(用Activity的实例来调用),取消注册的方法:unregisterReceiver(receiver),注册之后不取消会造成内存泄漏
如果一个BroadcastReceiver用于更新UI(UserInterface),那么通常会使用这种方法进行注册,在Activity启动的时候进行注册,在Activity不可见后取消注册;
清单文件中有哪些信息
manifest:根节点,描述了package中所有的内容。
uses-permission:请求你的package正常运作所需赋予的安全许可。
permission: 声明了安全许可来限制哪些程序能你package中的组件和功能。
instrumentation:声明了用来测试此package或其他package指令组件的代码。
application:包含package中application级别组件声明的根节点。
activity:Activity是用来与用户交互的主要工具。
receiver:IntentReceiver能使的application获得数据的改变或者发生的操作,即使它当前不在运行。
service:Service是能在后台运行任意时间的组件。
provider:ContentProvider是用来管理持久化数据并发布给其他应用程序使用的组件。
安卓6.0到8.0的变化 以及适配
6.0:的动态申请权限,部分危险的敏感权限,需要用户手动去授权
7.0:目录访问权限被限制,用清单文件中注册FileProvider,指定共享目录,访问目录是使用FileProvider(拍照和安装应用)
8.0:未知应用程序安装(在清单文件中添加权限);notification发送需要注册Notification_ID(tagetVersion<8.0可以解决)
安卓中有几种动画,区别
补间动画:缩放,平移、旋转、淡化、可以使用xml和代码两种方式生成,动画仅仅改变view的显示方式,不会改变view的属性值(大小、位置、事件)
帧动画:对多张图片进行一帧一帧的播放类似于GIF
属性动画:改变显示效果和属性
Android中数据存储方式
使用SharedPreferences存储数据
文件存储数据
SQLite数据库存储数据
使用ContentProvider存储数据
网络存储数据
安卓的屏幕适配
创建不同分辨率的layout、value
多用RelativeLayout和LinearLayout 多用权重
多套切图
开发中常用的布局
FrameLayout(帧布局)所有东西都依次放在左上角,会重叠
LinearLayout(线性布局)按照水平或者垂直进行数据展示
RelativeLayout(相对布局)一某一个元素为参照物,来定位的布局方式
TIP:RelativeLayout会让子View调用两次onMesure方法,分别计算垂直和水平方向的大小,LinearLayout在设置了weight的时候才会让子View调用两次onMesure(),根据实际情况来用布局
不常见布局:TableLayout和AbsolutLayout
ListView优化
ViewHolder优化,使用ViewHolder的原因是findViewById方法耗时较大,如果控件个数过多,会严重影响性能,而使用ViewHolder主要是为了可以省去这个时间。通过setTag,getTag直接获取View。
减少Item View的布局层级,这是所有layout都必须遵循的,布局层级过深会直接导致View的测量与绘制浪费大量的时间。
adapter中的getView方法尽量少使用逻辑
图片加载采用三级缓存,避免每次都要重新加载。(Glide)
尝试开启硬件加速来使ListView的滑动更加流畅。
使用 RecycleView 代替。
listView实现多条目以及分页加载
adapter 提供了 getViewTypeCount()和 getItemViewType(int position)两个方法。在 getView 方法中我们可以根据不同的 viewtype 加载不同的布局文件。
Activity和Fragment的交互方式,传值
交互:1、Activity中getFragmentById()可以获取到fragment的实例,2、Frgament中getActivity()可以获取到Activity的实例;3、通过接口的方式调用;4、广播;
传值:getArguments()
Service是运行在主线程中吗?广播呢?
Service、广播、Activity都是运行到主线程中的
intent可以传递的数据类型
基本数据类型、bundle、实现了Serializable或者Parcelable接口的类
Serializable和Parcelable的区别
如果存储在内存中,推荐使用parcelable,使用serialiable在序列化的时候会产生大量的临时变量,会引起频繁的GC
如果存储在硬盘上,推荐使用Serializable,虽然serializable效率较低
Serializable的实现:只需要实现Serializable接口,就会自动生成一个序列化id
Parcelable的实现:需要实现Parcelable接口,还需要Parcelable.CREATER变量
scrollView嵌套ListView会出现的问题,以及解决方法
在 ScrollView 添加一个 ListView 会导致 listview 控件显示不全,通常只会显示一条,这是因为两个控件的滚动事件冲突导致。所以需要通过 listview 中的 item 数量去计算 listview 的显示高度,从而使其完整展示。
现阶段最好的处理的方式是: 自定义 ListView,重载 onMeasure()方法, 设置全部显示。
ListView的图片错位是怎么产生的 以及解决办法
图片错位问题的本质源于我们的 listview 使用了缓存 convertView, 假设一种场景, 一个 listview一屏显示九个 item,那么在拉出第十个 item 的时候,事实上该 item 是重复使用了第一个 item,也就是说在第一个 item 从网络中下载图片并最终要显示的时候,其实该 item 已经不在当前显示区域内了,此时显示的后果将可能在第十个 item 上输出图像,这就导致了图片错位的问题。所以解决办法就是可见则显示,不可见则不显示。
Fragment的replace和add的区别
Fragment 本身并没有 replace 和 add 方法,FragmentManager才有replace和add方法。我们经常使用的一个架构就是通过RadioGroup切换Fragment,每个 Fragment 就是一个功能模块。
Fragment 的容器一个 FrameLayout,add 的时候是把所有的 Fragment 一层一层的叠加到了。FrameLayout 上了,而 replace 的话首先将该容器中的其他 Fragment 去除掉然后将当前Fragment添加到容器中。
一个 Fragment 容器中只能添加一个 Fragment 种类,如果多次添加则会报异常,导致程序终止,而 replace 则无所谓,随便切换。因为通过 add 的方法添加的 Fragment,每个 Fragment 只能添加一次,因此如果要想达到切换效果需要通过 Fragment 的的 hide 和 show 方法结合者使用。将要显示的 show 出来,将其他 hide起来。这个过程 Fragment 的生命周期没有变化。
通过 replace 切换 Fragment,每次都会执行上一个 Fragment 的 onDestroyView,新 Fragment的 onCreateView、onStart、onResume 方法。基于以上不同的特点我们在使用的使用一定要结合着生命周期操作我们的视图和数据。
以上内容就是Android的初级面试题了,还有中高级面试题和java基础面试题,下面只是总结了一下面试的问题,没有具体答案,答案的话会在以后的推送里面写,希望大家能够持续关注!
Android中高级面试题
Android中ARN的情况,怎么解决
Android中OOM的情况,怎么解决
内存泄漏和内存溢出的区别,怎么避免,什么情况下回内存溢出
启动一个应用程序可以从桌面入口进去,也可以从别的应用跳转进去,这样有什么区别
Activity因为某些原因被回收了,状态怎么保存
Activity中的context和AppLication的Context有什么区别
AIDL是什么简要说明(了解)
自定义View的流程(View的绘制流程)
bitmap的内存计算公式(如何压缩)
如何对安卓进行优化(内存泄漏的解决方式)
描述一下handler的原理
Android的数字签名,以及上线打包流程
简要说出图片加载框架的原理,
Eventbus的实现原理
Volly的实现原理
如何对安卓程序进行分析
捕获异常的第三方框架Bugly
线程的通信方式
Activity、window、View的区别,以及Fragment的特点
描述一次网络请求的过程
View的绘制流程
Android中的事件传递
事件分发中onTouch和onTouchEvent的区别
怎么可以让程序在后台不被杀死
动画框架的实现原理
优化自定义View
ContentProvider
谈一谈MVP、MVC和MVVM
java基础面试题
接口和抽象类的意义 以及区别
内部类的作用
父类的静态方法可不可以被重写,为什么
举例两个排序算法
说出java中的集合以及继承关系
线程和进程的区别
java中“==”和“equals”的区别
虚拟机的特性
垃圾回收机制的原理
ArrayList和HashMap的实现原理
int和Integer的区别
String StringBuffer和StringBuild的区别
java多态
线程的生命周期(状态)
线程在什么情况下会被堵塞
java中有几种创建线程的办法
什么情况下会造成死锁
以上是关于安卓面试题的主要内容,如果未能解决你的问题,请参考以下文章