最近开始踏上找工作的步伐,总结一下常见的问题
1.Android的三类动画及优缺点
(1)Frame Animation(帧动画)主要用于播放一帧帧准备好的图片,类似GIF图片,优点是使用简单方便、缺点是需要事先准备好每一帧图片;
(2)Tween Animation(补间动画)仅需定义开始与结束的关键帧,而变化的中间帧由系统补上,优点是不用准备每一帧,缺点是只改变了对象绘制,而没有改变View本身属性。因此如果改变了按钮的位置,还是需要点击原来按钮所在位置才有效。
(3)Property Animation(属性动画)是3.0后推出的动画,优点是使用简单、降低实现的复杂度、直接更改对象的属性、几乎可适用于任何对象而仅非View类,缺点是需要3.0以上的API支持,限制较大!
2.handler机制的原理
3.说说MVC模式的原理,它在android中的运用
MVC全名是ModelViewController,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。其中M层处理数据,业务逻辑等;V层处理界面的显示结果;C层起到桥梁的作用,来控制V层和M层通信以此来达到分离视图显示和业务逻辑层。
采用MVC模式的好处是便于UI界面部分的显示和业务逻辑,数据处理分开。
4.让Activity变成一个窗口
让Activity变成一个窗口:Activity属性设定
讲点轻松的吧,可能有人希望做出来的应用程序是一个漂浮在手机主界面的东西,那么很
简单你只需要设置 一下Activity的主题就可以了在AndroidManifest.xml 中定义 Activity的地方一句话:
Xml代码
android :theme="@android:style/Theme.Dialog"
android:theme="@android:style/Theme.Dialog"
这就使你的应用程序变成对话框的形式弹出来了,或者透明的主题
Xml代码
android:theme="@android:style/Theme.Translucent"
android:theme="@android:style/Theme.Translucent"
5.简述activity的几种启动模式,并举例说明他的用处。
Activity的启动模式主要有以下四种
Standard、singleTop、singleTask、singleInstance
Standard:默认模式,可以不用写配置。在这个模式下,都会默认创建一个新的实例。因此,在这种模式下,可以有多个相同的实例,也允许多个相同Activity叠加。
singleTop:可以有多个实例,但是不允许多个相同Activity叠加。即,如果Activity在栈顶的时候,启动相同的Activity,不会创建新的实例,而会调用其onNewIntent方法。
singleTask:只有一个实例。在同一个应用程序中启动他的时候,若Activity不存在,则会在当前task创建一个新的实例,若存在,则会把task中在其之上的其它Activity destory掉并调用它的onNewIntent方法。
例如:现在栈的情况为:A B C D。B的Launch mode为singleTask,此时D通过Intent跳转到B,则栈的情况变成了:A
B。而C和D被弹出销毁了,也就是说位于B之上的实例都被销毁了。
注意:singleTask模式的Activity不管是位于栈顶还是栈底,再次运行这个Activity时,都会destory掉它上面的Activity来保证整个栈中只有一个自己,切记切记
- singleInstance:只有一个实例,并且这个实例独立运行在一个task中,这个task只有这个实例,不允许有别的Activity存在。
6.你后台的Activity被系统回收怎么办
onSaveInstanceState方法
当你的程序中某一个Activity A 在运行时中,主动或被动地运行另一个新的Activity B
这个时候A会执行
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putLong("id", 1234567890);
}
B 完成以后又会来找A, 这个时候就有两种情况,一种是A被回收,一种是没有被回收,被回收的A就要重新调用onCreate()方法,不同于直接启动的是这回onCreate()里是带上参数savedInstanceState,没被收回的就还是onResume就好了。
if(savedInstanceState != null){
long id = savedInstanceState.getLong("id");
}
就像官方的Notepad教程 里的情况,你正在编辑某一个note,突然被中断,那么就把这个note的id记住,再起来的时候就可以根据这个id去把那个note取出来,程序就完整一些。这也是看你的应用需不需要保存什么,比如你的界面就是读取一个列表,那就不需要特殊记住什么,哦, 没准你需要记住滚动条的位置...
以及看视频时,有横屏切换到竖屏。
7.如何退出Activity?如何安全退出已调用多个Activity的Application?
-
对于单一Activity的应用来说,直接finish()即可。
-
调用多个Activity的Application
- 1、抛异常强制退出:
该方法通过抛异常,使程序ForceClose。
验证可以,但是,需要解决的问题是,如何使程序结束掉,而不弹出Force Close的窗口。 - 2、记录打开的Activity:
每打开一个Activity,就记录下来。在需要退出时,关闭每一个Activity即可。 - 3、发送特定广播:
在需要结束应用时,发送一个特定的广播,每个Activity收到广播后,关闭即可。 - 4、递归退出
在打开新的Activity时使用startActivityForResult,然后自己加标志,在onActivityResult中处理,递归关闭。
- 1、抛异常强制退出:
A Activity ->> B Activty A 中:
startActivtiyForResult();
onActivtyResult()中处理
B中:
setResult();
finish();
8.请介绍下Android中常用的布局
- 线性布局LinearLayout
- 相对布局RelativeLayout
- 帧布局FrameLayout
- 表格布局TableLayou
以及一个不怎么常用的布局:绝对布局AbsoluteLayout
9.请介绍下Android的数据存储方式。
五种:
SharedPreferences存储数据;文件存储数据;SQLite数据库存储数据;ContentProvider存储数据;网络存储数据。
10.请介绍下ContentProvider是如何实现数据共享的
Android提供了ContentProvider,一个程序可以通过实现一个ContentProvider的抽象接口将自己的数据完全暴露出去,而且ContentProviders是以类似数据库中表的方式将数据暴露,也就是说ContentProvider就像一个“数据库”。那么外界获取其提供的数据,也就应该与从数据库中获取数据的操作基本一样,只不过是采用URI来表示外界需要访问的“数据库”。外部访问通过ContentResolver去访问并操作这些被暴露的数据。
11.AsyncTask 的异步机制和普通线程有什么区别,分别有哪些优缺点。
Asynctask就是thread+handler+线程池。
如果我们创建大量的(特别是在短时间内,持续的创建生命周期较长的线程)野生线程,往往会出现如下两方面的问题:
- 每个线程的创建与销毁(特别是创建)的资源开销是非常大的;
- 分享主线程的系统资源,从而会使主线程因资源受限而导致应用性能降低。
各位开发一线的前辈们为了解决这个问题,引入了线程池(ThreadPool)的概念,也就是把这些野生的线程圈养起来,统一的管理他们。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
AsyncTask详细解答
AsyncTask的缺陷
12.注册广播有几种方式,这些方式有何优缺点?请谈谈Android引入广播机制的用意。
在android下,要想接受广播信息,那么这个广播接收器就得我们自己来实现了,我们可以继承BroadcastReceiver,就可以有一个广播接收器了。有个接收器还不够,我们还得重写BroadcastReceiver里面的onReceiver方法,然后注册广播。
有两种方式:
- 一种是代码动态注册
生成广播处理
smsBroadCastReceiver = new SmsBroadCastReceiver();
实例化过滤器并设置要过滤的广播
IntentFilter intentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
注册广播
BroadCastReceiverActivity.this.registerReceiver(smsBroadCastReceiver, intentFilter);
2.还有静态AndroidManifest.xml中配置广播
<!--广播注册-->
<receiver android:name=".SmsBroadCastReceiver">
<intent-filter android:priority="20">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
两种注册类型的区别以及优缺点是:
1.第一种不是常驻型广播,也就是说广播跟随程序的生命周期,在灵活性方面有很大的优势,但是缺点也很明显,即必须在程序启动后才能接收广播。
2.第二种是常驻型,也就是说当应用程序关闭后,如果有信息广播来,程序也会被系统调用自动运行。
13.AIDL的全称是什么?如何工作?能处理哪些类型的数据?
AIDL的全称:Android Interface Definition Language,即Android接口定义语言。
14.什么是ANR 如何避免它?
ANR的定义:在Android上,如果你的应用程序有一段时间响应不够灵敏,系统会向用户显示一个对话框,这个对话框称作应用程序无响应(ANR:ApplicationNotResponding)对话框。用户可以选择让程序继续运行,但是,他们在使用你的应用程序时,并不希望每次都要处理这个对话框。因此,在程序里对响应性能的设计很重要,这样,系统不会显示ANR给用户。
如何避免:运行在主线程里的任何方法都尽可能少做事情,耗时操作需开辟一个子线程。
IntentReceiver执行时间的特殊限制意味着它应该做:在后台里做小的、琐碎的工作如保存设定或者注册一个
Notification。和在主线程里调用的其它方法一样,应用程序应该避免在BroadcastReceiver里做耗时的操作或计算。但不再是在子线程里做这些任务(因为BroadcastReceiver的生命周期短),替代的是,如果响应Intent广播需要执行一个耗时的动作的话,应用程序应该启动一个Service。
15.IntentService有何优点?
IntentService使用队列的方式将请求的Intent加入队列,然后开启一个workerthread(线程)来处理队列中的Intent,对于异步的startService请求,IntentService会处理完成一个之后再处理第二个,每一个请求都会在一个单独的worker thread中处理,不会阻塞应用程序的主线程。
16.横竖屏切换时候activity的生命周期?
- 不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
- 设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
- 设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法
总结一下整个Activity的生命周期
- 当前Activity产生事件弹出Toast和AlertDialog的时候Activity的生命周期不会有改变
- Activity运行时按下HOME键(跟被完全覆盖是一样的):onSaveInstanceState --> onPause --> onStop onRestart -->onStart--->onResume
- Activity未被完全覆盖只是失去焦点:onPause--->onResume
以及引申问题:竖屏Activity跳转到横屏Activity(或横竖屏切换),back返回黑屏解决
解决办法:
//在竖屏的Activity中添加:
android:configChanges="orientation"
android:screenOrientation="portrait"
17.Android基本架构
Android其本质就是在标准的Linux系统上增加了Java虚拟机Dalvik,并在Dalvik虚拟机上搭建了一个JAVA的application framework,所有的应用程序都是基于JAVA的application framework之上。
Android主要应用于ARM平台,但不仅限于ARM,通过编译控制,在X86、MAC等体系结构的机器上同样可以运行。
蓝色的代表java程序,黄色的代码为运行JAVA程序而实现的虚拟机,绿色部分为C/C++语言编写的程序库,红色的代码内核(linux内核+driver)。在ApplicationFramework之下,由C/C++的程序库组成,通过JNI完成从JAVA到C的调用。
android分为四个层,从高层到低层分别是应用程序层、应用程序框架层、系统运行库层和linux核心层。
各层详细参考这里
18.什么是Service以及描述下它的生命周期。Service有哪些启动方法,有什么区别,怎样停 用Service?
Service即服务,可以形象的理解为不可视化的Activity,它是Android中实现程序后台运行的解决方案,它适合用于去执行那些不需要与用户交互而且还要求长期运行的程序。
服务的生命周期如图
注:一个服务在调用了startService()方法后也可以调用bindservice()方法,那么如果要销毁的时候需要同时调用stopService()和unbindService()方法,onDestroy()方法才会执行。
19.Intent传递数据时,可以传递哪些类型数据?
Intent/Bundle支持传递基本类型的数据和基本类型的数组数据,以及String/CharSequence类型的数据和String/CharSequence类型的数组数据。而对于其它类型的数据貌似无能为力,其实不然,我们可以在Intent/Bundle的API中看到Intent/Bundle还可以传递Parcelable(包裹化,邮包)和Serializable(序列化)类型的数据,以及它们的数组/列表数据。
20.描述下Intent和 Intent Filter.
- Intent是Android程序中各个组件之间进行交互的一种重要方式,充当一个信使的作用。
- Intent Filter 则是一个意图过滤器。一个应用程序开发完成后,需要告诉Android系统自己能够处理哪些隐形的Intent请求,这就需要声明IntentFilter。
另附:如果说Intent是一个对动作和行为的抽象描述,负责组件之间程序之间进行消息传递。那么Broadcast Receiver组件就提供了一种把Intent作为一个消息广播出去,由所有对其感兴趣的程序对其作出反应的机制。
21.ListView如何提高其效率?
- 在适配器adapter中采用viewHolder模式以及用convertView回收视图。
- 预先缩放到视图大小,避免图片实时缩放。
图片加载的内存管理
22.Android系统中GC(垃圾回收器)什么情况下会出现内存泄露呢?
Java 内存泄露的根本原因就是 保存了不可能再被访问的变量类型的引用。
23.Android UI中的View如何刷新。
如果只是单纯的想要更新UI而不涉及到多线程的话,使用View.post()就可以了; 详细解答
需要另开线程处理数据以免阻塞UI线程,像是IO操作或者是循环,可以使用Activity.runOnUiThread();
如果需要传递状态值等信息,像是蓝牙编程中的socket连接,就需要利用状态值来提示连接状态以及做相应的处理,就需要使用Handler + Thread的方式;
如果是后台任务,像是下载任务等,就需要使用AsyncTask。
24.写出几种你认为可以提高Android程序运行效率的方法?
- 避免多余对象的创建
- 使用静态方法定义不会访问到对象内部的函数
- 使用Static Final定义常量
- 避免在类内部使用get/set方法
- ArrayList不使用增强型for循环
- 使用包级访问代替私有内联类的访问
- 使用double代替float
- 优先使用第三方类库而不是重复造轮子
- 谨慎使用NDK
- 不要执迷于性能神话
- 量化性能以及优化方法性能的量化,从而选择合适的优化方式
详细的介绍在此
25.ArrayList和LinkedList的区别
1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。
2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
4.查找操作indexOf,lastIndexOf,contains等,两者差不多。
5.随机查找指定节点的操作get,ArrayList速度要快于LinkedList.
GitHub上面一篇汇总文章,很nice
我是文