面试题基础储备第9期.docx
- 文档编号:2746886
- 上传时间:2023-05-04
- 格式:DOCX
- 页数:23
- 大小:420.25KB
面试题基础储备第9期.docx
《面试题基础储备第9期.docx》由会员分享,可在线阅读,更多相关《面试题基础储备第9期.docx(23页珍藏版)》请在冰点文库上搜索。
面试题基础储备第9期
面试题基础储备
1、Activity相关
a、Activity的特点
1、可见2、可交互
他之所以可交互,是因为他同时实现了Window.Callback和KeyEvent.Callback,可以处理与窗体用户交互的事件和按键事件.这两个特点,是他和service最大的区别。
一个Activity在创建与销毁的过程中,会经历一些生命周期。
b、Activity的生命周期
结论1、这个界面只要看不到了,它就一定执行了onStop方法
结论2、只要这个界面显示出来了,它就一定执行了onResume方法
结论3、onPause、onStop的情况下这个activity都有可能会系统回收。
(简单来说,只要这个activity不处于活跃状态,那么它就有可能被回收)
c、页面跳转必然会执行的方法
onResume,所以可以在onResume方法里面进行数据刷新,保证当前activity显示的都是最新状态
d、对话框的activity
启动activity默认是占满整个屏幕,如果想让这个activity以对话框的方式展示,则需要配置:
android:
theme="@android:
style/Theme.Dialog",此时它下面的activity并不会执行onStop方法,而是仅执行onPause方法
e、横竖屏切换
默认情况下,横竖屏切换的时候会重新创建新的activity,新的那个activity会执行onCreate方法。
可以通过AndroidManifest文件进行配置,让它横竖屏切换的时候不重新创建Activity,配置方法为
android:
configChanges="orientation|keyboardHidden|screenSize",配置之后就不会创建新的Activity,而是执行当前activity的onConfigurationChanged。
写死屏幕的方向:
在AndroidManifest中配置
android:
screenOrientation="landscape"
f、保存数据
除了在栈顶的activity,其他的activity在系统资源匮乏的时候,都有可能会被系统回收。
如果activity被系统没有onDestory的情况下就被系统回收了,这时候系统会调用onSaveInstanceState方法,我们可以往bundle里面存放数据。
在activityonCreate里面我们先判断一下bundle是不是为空,如果不为空,就代表这个activity之前被系统回收掉,应该恢复一下现场。
我们就可以从bundle里面取值。
g、栈相关
概念:
Android是用栈来管理Activity的,service是没有栈的。
所以在service启动activity一般要加上
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)来开辟一个新的栈。
四大组件中只有Activity是有栈的。
启动模式:
android:
launchMode,
standard:
默认的模式,没有限制,栈里爱有几个有几个
singleTop:
栈顶只有一个,栈内可以有多个
singleTask:
整个栈只有一个
singleInstance:
霸道,整个栈只有自己,单实例
h、onNewIntent
当启动某一个activity,这个activity在栈中存在,并且需要被复用的情况下,(也就是配置了singleTop、singleTask、singleInstance的属性),会调用此方法。
如果需要传递参数,需要在onNewIntent里面setIntent,这样才能更新这个activity的intent
具体面试题:
1、2、3、4、5、6、7、11、42
2、Service相关
a、Service的特点
不可见、不可交互,在后台运行的四大组件之一。
并不是所有的功能都需要界面。
比如音乐播放。
b、Service的启动方式
startService、bindService
c、Service的生命周期
a、通过startService
Service会经历onCreate到onStart,然后处于运行状态,stopService的时候调用onDestroy方法。
这种方式,activity和service是相互独立的。
如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行
b、通过bindService
Service会运行onCreate,然后是调用onBind,这个时候调用者和Service绑定在一起。
调用者解绑了,Service就会调用onUnbind->onDestroyed方法。
这种方式,activity就和service相互捆绑在一起了。
所谓绑定在一起就共存亡了。
调用者也可以通过调用unbindService方法来停止服务,这时候Service就会调用onUnbind->onDestroyed方法。
简单来说,startService的方式启动之后,Activity是调用不到Service里面的方法。
bindService方式启动之后,可以得到Service的实例,进而调用Service里面的方法。
startService和bindService可以结合使用。
无论怎么结合,Service的实例只有一个。
d、为什么使用Service
普通的线程也可以达到在后台做事情的功能,那么为什么使用Service呢?
是因为Service是系统的组件,它的优先级比普通的线程要高,不容易被系统回收。
而且线程不好控制,Service相对好控制一些。
运行在前台的Activity是不会被系统回收的,而Service如果不想被系统回收,就需要在Service中设置一下
startForeground(int,Notification)
具体的使用场景有:
a、拥有长连接QQ
b、定时轮询
c、服务里面注册广播接收者。
有些广播接收者只能通过代码注册,比如屏幕锁屏、屏幕解锁、电量发生变化等。
e、IntentService
普通的service,默认运行在uimain主线程.Sdk给我们提供的方便的、带有异步处理的service类,我们可以在OnHandleIntent()处理耗时的操作
四大组件都是运行在主线程中
具体面试题:
8、10、12、13、14、15、16、17、64、68
3、数据相关
a、存储
在Android中数据可以存储在四个地方
内存:
读写速度最快,临时的值,程序退出或者界面退出就没有了
SharedPreference:
持久存储,主要保存一些配置信息,如一个功能的开关
Sqlite:
持久存储,关系型数据库,针对数据之间有很强关系的情况
文件:
持久存储,针对数据量较大、并且没啥关联的数据
关于如何使用Sqlite来存储数据,传统的方式我们会使用到SQLiteOpenHelper ,然后会自己写一些sql语句,在真实的开发当中,我们往往会借助于一些第三方框架帮我们处理数据相关的逻辑,这样可以帮助我们帮主要精力花在其他功能实现上。
我比较常用的是LitePal,它可以帮我们很轻松的进行数据库操作。
b、传递
a、通过intent传递
基本的数据类型:
String、int、float等
对象:
这个对象必须继承Parcelable接口。
继承Parcelable接口代表这个对象可以被序列化到内存中,和Serializable类似,只不过Serializable是将对象写到文件当中。
b、通过Application传递
Application的特点:
一个应用程序运行的时候只有一个,它的生命周期是最长的,比Activity、Service都长,只要这个程序在运行,无论是否在前台,它都会有一个Application对象。
往Application存某一些对象,在页面跳转的时候会非常方便。
c、通过View来传递数据。
在给View设置点击事件的时候,可以通过view.setTag来传递所需要传递的数据
c、解析
XML
效率低,体积大
JSON
效率高,体积小,使用广,可以使用Gson解析,也可以使用JSONObject进行解析,fastjson\其他第三方框架
复杂的结构:
使用Gson,创建javabean来进行解析
简单的结构:
{"success":
"true"},直接使用JSONObject进行解析.如果使用JSONObject进行解析的话,有几点需要记忆:
{}---JSONObject
[]---JSONArray
无符号:
基础数据类型
d、ContentProvider
目的:
将自己应用的数据提供给其他应用
把自己的数据通过uri的形式共享出去,这个uri是事先约定好的。
android系统下不同程序数据默认是不能共享访问,通过ContentProvider可以将自己应用的数据提供给别的应用。
我们在写内容提供者的时候,需要写一个类继承ContentProvider,然后实现里面的增删改查方法
query(Uri,String[],String,String[],String)
insert(Uri,ContentValues)
update(Uri,ContentValues,String,String[])
delete(Uri,String,String[])
工作中用的很少,我们几乎不需要写ContentProvider,因为没有这个需求。
可能会用到的是调用系统的ContentProvider,比如获取系统联系人,系统短信。
具体面试题:
9、19、23、24、25
4、广播相关
a、广播发送
广播的发送有两类,一种是系统本身就有的,一种是我们自己写的广播。
发送方式:
有序广播sendOrderedBroadcast
按顺序依次的发送给每一个接收者,而每一个接收者在收到这个广播的时候,可以将这个广播abort掉,也可以将这个广播继续传递到下一个广播接收者。
广播接收者在注册的时候可以指定优先级,用于提高接收到广播的顺序。
无序广播sendBroadcast
不能被abort掉
b、广播接收
广播接收者注册的方式也有两种,一种是动态注册,一种是静态注册。
有一些系统的广播只能使用动态注册,这种广播产生的频率是比较高的。
比如电量变化的广播,屏幕解锁的广播。
电量变化的广播。
c、广播的作用
广播一般是用于跨进程通讯的时候。
两个进程间要进行通讯的情况下,使用广播显得非常的方便。
如打电话的时候状态栏颜色变了,此时就是可以使用广播在电话的进程中发送一个广播,然后再状态栏的进程当中进行接收。
接收到之后改变状态栏颜色。
onReceive方法也是在主线程当中运行的。
在广播中启动Activity也是需要配置
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)来开辟一个新的栈。
具体面试题:
21、22
5、跨进程访问
a、Android中跨进程访问的方式:
主要有三种:
1、广播2、AIDL3、intent启动其他应用activity、内容提供者
b、什么是AIDL:
AIDL的全称是androidinterfacedefinitionlanguage接口定义语言。
它所做的事情就是跨进程调用另外一个服务里面的方法的。
所以aidl就得使用到bindService方法。
在手机卫士中挂断电话用到过AIDL。
我们要获取手机系统的电话服务,用到了aidl它其实工作的原理就是绑定到一个远程的服务上。
然后这个远程服务会返回回来一个代理对象。
这个代理对象里面的方法,就是我们定义的aidl里面的方法。
aidl的写法也非常简单,主要分两种。
调用系统服务的话,直接找到那个服务的aidl拷贝到我们的项目中就可以了。
另外一种是我们自己写aidl,主要注意的一点是aidl是没有访问修饰符的。
因为aidl本身就是公开的,就是为了给别人调用的,不需要私有的private方法。
其实,在实际的开发过程中,比较少会写这个aidl,但是你得懂它相关的知识点。
在面试的时候,这个也是经常被问的。
所以大家要熟悉这个问题的回答方法。
我以前面试别人的时候,只要他能回答上几个关键点,我就会让他过我这关噢。
1、跨进程2、aidl在服务端和客户端都需要有一份3、通过绑定bindService的方式获取远程服务对象的代理IBinder,就可以调用相关的方法。
c、跨进程的底层原理
广播、aidl的底层实现机制是Binder,Binder是基于共享内存的一种IPC方式
如何自己实现进程间的通信?
具体面试题:
30、32、44、52
6、Handler相关
a、为什么使用Handler
Handler是用来进行线程间的通信。
因为Android系统有一个特性,ui操作必须得在主线程当中进行。
所以在子线程进行完耗时操作的时候,如何告诉主线程进行ui界面更新,这就需要使用到线程间的通讯了。
b、Handler、Looper、MessageQueue、Message的关系
任何一个线程,无论是子线程还是主线程,都维护着一个消息队列,这个消息队列就是MessageQueue,有了这个消息队列之后,是需要不断的从这个消息队列里面取出消息进行处理的,这个就是Looper做的事情。
那么,谁往这个消息队列里面丢消息呢?
那就是Handler了。
Looper是用来管理所属线程的消息队列MessageQueue的。
每一个线程都需要有一个looper,每一个looper管理一个MessageQueue.
Handler.sendMessage的意思是将某一个message放到MessageQueue中去,looper是个死循环,不断的读MessageQueue中的新消息。
要让looper的死循环运行起来,得调用Looper.loop()方法。
我们通常都会在子线程中,发一个消息到主线程中的messagequeue中去。
Handler到底是往主线程的MessageQueue发送消息呢还是往子线程的MessageQueue发送消息呢?
这取决于Handler在哪里创建。
如果Handler在主线程中创建,那么这个Handler就会把消息发到主线程的消息队列,如果Handler是在子线程中创建,这个Handler就会把消息发到子线程的消息队列。
这里需要注意的是,子线程的Looper需要我们自己手动启动,要调用Looper.prepare()和Looper.loop()方法,主线程的Looper系统已经帮我们启动了,因此我们不需要为主线程的Looper调用loop()方法
c、子线程-->主线程主线程-->子线程?
view.post(r)或者activity.runOnUiThread(r)都是将runnable对象丢到了主线程的消息队列中。
具体面试题:
29、33、56
7、ANR相关
a、什么是ANR:
ANR是androidnotresponse安卓无响应,这里指的是主线程无响应。
将耗时的操作放在子线程中进行可以有效的避免ANR。
b、出现的原因:
消息的超时信息
出现ANR的根本原因是主线程堵塞了,来不及处理消息。
任何UI操作都是一个消息,比如触摸、按键,弹框,setText等,当这些消息得不到及时的处理,就会出现ANR了。
每一个发往主线程的消息其实都带有一个超时时间,超过了这个时间,这个消息还没有处理,就会出现ANR
Activity的超时:
5s
BroadcastReceiver超时:
10s
Service超时:
20s
c、解决的方法
如果出现了ANR,我们可以通过log信息以及traces.txt文件进行分析。
traces.txt里面记录的是stack信息。
traces.txt的路径:
/data/anr/traces.txt
具体面试题:
58、
8、ListView的相关
a、ListView为什么要优化?
因为不优化的话,滑动ListView会卡顿。
卡顿的原因在于getView太耗时了。
getView是在主线程执行的,如果这里面太耗时的话,ui肯定卡顿。
耗时主要集中在两个方面:
加载布局文件、findViewById
b、ListView怎么优化
减少加载布局文件的次数:
使用缓存convertView
减少findViewById的次数:
使用ViewHolder
c、数据错乱的问题
i、正是因为使用了缓存,所以才有可能造成数据错乱。
所以在刷新数据的时候,一定要考虑周全。
ii、消息处理时机引起的数据错乱
d、ListView展示多种布局类型
i、告诉系统你有几种布局类型getViewTypeCount
ii、告诉系统,什么情况下显示哪种布局类型getItemViewType(intposition)
iii、在getView中根据getItemViewType的返回值加载对应的布局文件。
在刷新数据的时候也得根据getItemViewType的返回值进行数据刷新。
具体面试题:
38、
9、自定义控件相关
a、自定义属性
步骤:
1、起一个名字
在values的目录下需要建立一个文件,叫做attrs.xml这个文件是定义属性规则的。
一个属性的名字、取值类型、取值范围
2、用这个属性
在布局文件中需要加入命名空间
3、得到这个属性的值
最后在自定义控件中获取这些值。
方式一:
方式二
b、绘制流程
涉及的方法:
onMeasure:
计算大小
onLayout:
计算位置
onDraw:
开始绘制
调用顺序是onMeasure-->onLayout--->onDraw
这三个方法是任何一个View在屏幕上呈现出来的时候都一定会调用的三个方法,三个方法的作用不一样。
其他知识:
intwidthMeasureSpec---封装了两个信息,一个是具体大小的值,一个是模式
模式就是父控件对你的限制。
intwidthSize=MeasureSpec.getSize(widthMeasureSpec);//获取宽度
intwidthMode=MeasureSpec.getMode(widthMeasureSpec);//宽度的模式
//MeasureSpec.AT_MOST;--->wrap_content至多的模式。
//MeasureSpec.EXACTLY;--->确定的模式,match_parent,写死成多少dp
//MeasureSpec.UNSPECIFIED;--->未确定的模式ScrollView:
不对孩子的高度进行限定
c、其他
onFinishInflate、onSizeChanged
拖拽事件:
借助ViewDragHelper
动画的实现:
属性动画、伴随动画(中间值的计算)start+(end-star)*percent
事件的通知:
观察者设计模式
回答自定义控件相关的问题最好根据自身的开发经验开展
具体面试题:
35
10、动画相关
分类
a、帧动画
帧动画,就像GIF图片
b、补间动画tween
只是改变了View对象绘制的流程,而没有改变View对象本身。
AlphaAnimation、RotateAnimation、ScaleAnimation、TranslateAnimation
c、属性动画
Android3.0中才引进,更改的是对象的实际属性。
如果要在2.x版本也要支持属性动画,则需要加入兼容包nineoldandroids.jar
ValueAnimator、ObjectAnimator的使用
具体面试题:
59
11、设计模式相关
a、单例:
保证就只有一个实例
单例的写法:
1、私有的构造方法
2、私有的,静态的对象instance
3、公开的,静态的getInstance方法
注意事项:
在getInstance的方法前加上线程同步synchronized
b、适配器:
数据和View的桥梁。
c、观察者:
本质就是回调,一堆回调
d、MVC:
MVC是Model、View、Controller三部分组成的。
其中View主要由xml布局文件,或者用代码编写动态布局来体现。
Model是数据模型,其实类似javabean,不过这些JavaBean封装了对数据库、网络等的操作。
Controller一般由Activity负责,它根据用户的输入,控制用户界面数据的显示及更新model对象的状态,它通过控制View和Model跟用户进行交互。
MVC在Android当中体现的并不是很明显,在web当中体现的明显些。
回答设计模式相关的问题时,应该结合自身的开发经历进行开展。
12、屏幕适配相关
a、概述:
用dp不用px这仅仅是适配的一部分而已。
这里需要注意的一点是,android是不可能做到完全适配每一个屏幕的,只能达到大体相近。
如果你要达到完全适配,你就必须在每一个drawable-目录下都放入整套切图,而且要建立不同分辨率的layout-854*480的布局文件,这简直是不可想象。
没有一个公司会这么做。
大部分的人是怎么做的呢?
b、切图适配:
一般都是找一个使用比较广泛的分辨率当作标准。
比如1280x720密度为2,然后设计师就会根据这个分辨率进行设计,然后切图。
我们就需要将设计师出的切图放到drawable-xhdpi目录下就可以了。
一般情况下,我们不需要在drawable-hdpi目录、drawable-mdpi目录、drawable-xxhdpi目录下放切图了,只在drawable-xhdpi下放一套就够了。
在真正运行的时候,系统会自动对图片进行处理。
这时候,绝大部分切图显示都是正常的
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 试题 基础 储备