Android 面试题总结之Android 基础
Posted fuchenxuan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 面试题总结之Android 基础相关的知识,希望对你有一定的参考价值。
android 面试题总结之Android 基础(二)
上一篇面试总结,主要讲了Activity 和Intent ,这篇主要讲剩下的四大组件,面试中基础较多的就是四大组件,需要了解的知识点也很多。上一篇文章
Android 面试题总结之Android 基础(一)
Service
-
Service 是否在 main thread 中执行, service 里面是否 能执行耗时的操作?
默认情况,如果没有显示的指 servic 所运行的进程, Service 和 activity 是运 行在当前 app 所在进程的 main thread(UI 主线程)里面。
service 里面不能执行耗时的操作(网络请求,拷贝数据库,大文件 )
特殊情况 ,可以在清单文件配置 service 执行所在的进程 ,让 service 在另 外的进程中执行
<service android:name="com.baidu.location.f" android:enabled="true" android:process=":remote" >
</service>
Activity 怎么和 Service 绑定,怎么在 Activity 中启动自 己对应的 Service?
Activity 通过 bindService(Intent service, ServiceConnection conn, int flags)跟 Service 进行绑定,当绑定成功的时候 Service 会将代理对象通过回调 的形式传给 conn,这样我们就拿到了 Service 提供的服务代理对象。
在 Activity 中可以通过 startService 和 bindService 方法启动 Service。一 般情况下如果想获取 Service 的服务对象那么肯定需要通过 bindService()方 法,比如音乐播放器,第三方支付等。如果仅仅只是为了开启一个后台任务那么 可以使用 startService()方法。-
Service 的生命周期
Service 有绑定模式和非绑定模式,以及这两种模式的混合使用方式。不同 的使用方法生命周期方法也不同。
非绑定模式:当第一次调用 startService 的时候执行的方法依次为 onCreate()、onStartCommand(),当 Service 关闭的时候调用 onDestory 方 法。
绑定模式:第一次 bindService()的时候,执行的方法为 onCreate()、 onBind()解除绑定的时候会执行 onUnbind()、onDestory()。
上面的两种生命周期是在相对单纯的模式下的情形。我们在开发的过程中还 必须注意 Service 实例只会有一个,也就是说如果当前要启动的 Service 已经存 在了那么就不会再次创建该 Service 当然也不会调用 onCreate()方法。
一个 Service 可以被多个客户进行绑定,只有所有的绑定对象都执行了
onBind()方法后该 Service 才会销毁,不过如果有一个客户执行了 onStart() 方法,那么这个时候如果所有的 bind 客户都执行了 unBind()该 Service 也不会 销毁。Service 的生命周期图如下所示,帮助大家记忆。
-
什么是 IntentService?有何优点?
我们通常只会使用 Service,可能 IntentService 对大部分同学来说都是第 一次听说。那么看了下面的介绍相信你就不再陌生了。如果你还是不了解那么在 面试的时候你就坦诚说没用过或者不了解等。并不是所有的问题都需要回答上来的。
一、IntentService 简介
IntentService 是 Service 的子类,比普通的 Service 增加了额外的功能。
先看 Service 本身存在两个问题:
Service 不会专门启动一条单独的进程,Service 与它所在应用位于同一个进
程中;
Service 也不是专门一条新线程,因此不应该在 Service 中直接处理耗时的
任务;
二、IntentService 特征
会创建独立的 worker 线程来处理所有的 Intent 请求;
会创建独立的 worker 线程来处理 onHandleIntent()方法实现的代码,无需
处理多线程问题;
所有请求处理完成后,IntentService 会自动停止,无需调用 stopSelf()方法
停止 Service;
为 Service 的 onBind()提供默认实现,返回 null;
为 Service 的 onStartCommand 提供默认实现,将请求 Intent 添加到队列
中;
使用 IntentService
本人写了一个 IntentService 的使用例子供参考。该例子中一个
MainActivity 一个 MyIntentService,这两个类都是四大组件当然需要在清单 文件中注册。这里只给出核心代码:MainActivity.java: public void click(View view) Intent intent = new Intent(this, MyIntentService.class); intent.putExtra("start", "MyIntentService"); startService(intent); MyIntentService.java public class MyIntentService extends IntentService private String ex = ""; private Handler mHandler = new Handler() public void handleMessage(android.os.Message msg) Toast.makeText(MyIntentService.this, "-e " + ex, Toast.LENGTH_LONG).show(); ; public MyIntentService() super("MyIntentService"); @Override public int onStartCommand(Intent intent, int flags, int startId) ex = intent.getStringExtra("start"); return super.onStartCommand(intent, flags, startId); @Override protected void onHandleIntent(Intent intent) /** * 模拟执行耗时任务 * 该方法是在子线程中执行的,因此需要用到 handler 跟主线程进行通信 */ try Thread.sleep(1000); catch (InterruptedException e) e.printStackTrace(); mHandler.sendEmptyMessage(0); try Thread.sleep(1000); catch (InterruptedException e) e.printStackTrace();
-
说说 Activity、Intent、Service 是什么关系
他们都是 Android 开发中使用频率最高的类。其中 Activity 和 Service 都是 Android 四大组件之一。他俩都是 Context 类的子类 ContextWrapper 的子类, 因此他俩可以算是兄弟关系吧。不过兄弟俩各有各自的本领,Activity 负责用户 界面的显示和交互,Service 负责后台任务的处理。Activity 和 Service 之间可 以通过 Intent 传递数据,因此可以把 Intent 看作是通信使者。
Service 和 Activity 在同一个线程吗
对于同一 app 来说默认情况下是在同一个线程中的,main Thread (UI Thread)。Service 里面可以弹吐司么
可以的。弹吐司有个条件就是得有一个 Context 上下文,而 Service 本身就是 Context 的子类,因此在 Service 里面弹吐司是完全可以的。比如我们在 Service 中完成下载任务后可以弹一个吐司通知用户。-
什么是 Service 以及描述下它的生命周期。Service 有哪 些启动方法,有什么区别,怎样停用 Service?
在 Service 的生命周期中,被回调的方法比 Activity 少一些,只有 onCreate, onStart, onDestroy,
onBind 和 onUnbind。
通常有两种方式启动一个 Service,他们对 Service 生命周期的影响是不一样的。- 通过 startService
Service 会经历 onCreate 到 onStart,然后处于运行状态,stopService
的时候调用 onDestroy 方法。
如果是调用者自己直接退出而没有调用 stopService 的话,Service 会一直
在后台运行。 - 通过 bindService
Service 会运行 onCreate,然后是调用 onBind,这个时候调用者和 Service 绑定在一起。调用者退出了,Srevice 就会调用 onUnbind->onDestroyed 方 法。
所谓绑定在一起就共存亡了。调用者也可以通过调用 unbindService 方法来 停止服务,这时候 Srevice 就会调用 onUnbind->onDestroyed 方法。 需要注意的是如果这几个方法交织在一起的话,会出现什么情况呢? 一个原则是 Service 的 onCreate 的方法只会被调用一次,就是你无论多少次的 startService 又 bindService,Service 只被创建一次。
如果先是 bind 了,那么 start 的时候就直接运行 Service 的 onStart 方法,如 果先是 start,那么 bind 的时候就直接运行 onBind 方法。
如果 service 运行期间调用了 bindService,这时候再调用 stopService 的话,service 是不会调用 onDestroy 方法的,service 就 stop 不掉了,只能调用 UnbindService, service 就会被销毁
如果一个 service 通过 startService 被 start 之后,多次调用 startService 的 话,service 会多次调用 onStart 方法。多次调用 stopService 的话,service 只会调用一次 onDestroyed 方法。
如果一个 service 通过 bindService 被 start 之后,多次调用 bindService 的话, service 只会调用一次 onBind 方法。
多次调用 unbindService 的话会抛出异常。
- 通过 startService
在 service 的生命周期方法 onstartConmand()可不 可以执行网络操作?如何在 service 中执行网络操作?
可以直接在 Service 中执行网络操作,在 onStartCommand()方法中可以执行网络操作
Broadcast Receiver
-
BroadcastReceiver 简介
BroadCastReceiver 是 Android 四大组件之一,主要用于接收系统或者 app 发 送的广播事件。
广播分两种:有序广播和无序广播。
内部通信实现机制:通过 Android 系统的 Binder 机制实现通信。 无序广播:完全异步,逻辑上可以被任何广播接收者接收到。优点是效率较高。 缺点是一个接收者不能将处理结果传递给下一个接收者,并无法终止广播 intent 的传播。 有序广播:按照被接收者的优先级顺序,在被接收者中依次传播。比如有三个广 播接收者 A,B,C,优先级是 A > B > C。那这个消息先传给 A,再传给 B,最 后传给 C。每个接收者有权终止广播,比如 B 终止广播,C 就无法接收到。此外 A 接收到广播后可以对结果对象进行操作,当广播传给 B 时,B 可以从结果对象
中取得 A 存入的数据。在通过 Context.sendOrderedBroadcast(intent, receiverPermission, resultReceiver, scheduler, initialCode, initialData, initialExtras)时我们可以 指定 resultReceiver 广播接收者,这个接收者我们可以认为是最终接收者,通 常情况下如果比他优先级更高的接收者如果没有终止广播,那么他的 onReceive 会被执行两次,第一次是正常的按照优先级顺序执行,第二次是作为最终接收者 接收。如果比他优先级高的接收者终止了广播,那么他依然能接收到广播。 在我们的项目中经常使用广播接收者接收系统通知,比如开机启动、sd 挂载、 低电量、外播电话、锁屏等。 如果我们做的是播放器,那么监听到用户锁屏后我们应该将我们的播放之暂停 等。
在 manifest 和代码中如何注册和使用 BroadcastReceiver
在清单文件中注册广播接收者称为静态注册,在代码中注册称为动态注册。 静态注册的广播接收者只要 app 在系统中运行则一直可以接收到广播消息,动 态注册的广播接收者当注册的 Activity 或者 Service 销毁了那么就接收不到广播 了。
静态注册:在清单文件中进行如下配置
"><action android:name="android.intent.action.CALL" >
</action>
</intent-filter>
</receiver>
动态注册:在代码中进行如下注册
IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(CALL_ACTION); context.registerReceiver(receiver, intentFilter);
BroadCastReceiver 的生命周期
a. 广播接收者的生命周期非常短暂的,在接收到广播的时候创建, onReceive()方法结束之后销毁;
b. 广播接收者中不要做一些耗时的工作,否则会弹出 Application No Response 错误对话框;
c. 最好也不要在广播接收者中创建子线程做耗时的工作,因为广播接收者被 销毁后进程就成为了空进程,很容易被系统杀掉;
d. 耗时的较长的工作最好放在服务中完成;Android 引入广播机制的用意
a. 从 MVC 的角度考虑(应用程序内) 其实回答这个问题的时候还可以这样问,
android 为什么要有那 4 大组件,现在的移动开发模型基本上也是照搬的 web 那一套 MVC 架构,只不过是改了点嫁妆而已。android 的四大组件本 质上就是为了实现移动或者说嵌入式设备上的 MVC 架构,它们之间有时候 是一种相互依存的关系,有时候又是一种补充关系,引入广播机制可以方便 几大组件的信息和数据交互。
b. 程序间互通消息(例如在自己的应用程序内监听系统来电)
c. 效率上(参考 UDP 的广播协议在局域网的方便性)
d. 设计模式上(反转控制的一种应用,类似监听者模式)
ContentProvider
-
ContentProvider 是如何实现数据共享的
在 Android 中如果想将自己应用的数据(一般多为数据库中的数据)提供 给第三发应用,那么我们只能通过 ContentProvider 来实现了。
ContentProvider 是应用程序之间共享数据的接口。使用的时候首先自定义 一个类继承 ContentProvider,然后覆写 query、insert、update、delete 等 方法。因为其是四大组件之一因此必须在 AndroidManifest 文件中进行注册。
把自己的数据通过 uri 的形式共享出去
android 系统下 不同程序 数据默认是不能共享访问 需要去实现一个类去继承 ContentProviderpublic class PersonContentProvider extends ContentProvider public boolean onCreate() query(Uri, String[], String, String[], String) insert(Uri, ContentValues) update(Uri, ContentValues, String, String[]) delete(Uri, String, String[]) <provider
第三方可以通过 ContentResolver 来访问该 Provider。
-
Android 的数据存储方式
a. File 存储
b. SharedPreference 存储
c. ContentProvider 存储
d. SQLiteDataBase 存储
e. 网络存储 -
为什么要用 ContentProvider?它和 sql 的实现上有什么差别?
ContentProvider 屏蔽了数据存储的细节,内部实现对用户完全透明,用户只 需要关心操作数据的 uri 就可以了,ContentProvider 可以实现不同 app 之间 共享。
Sql 也有增删改查的方法,但是 sql 只能查询本应用下的数据库。而 ContentProvider 还可以去增删改查本地文件. xml 文件的读取等。 -
说 说 ContentProvider 、 ContentResolver 、 ContentObserver 之间的关系
a. ContentProvider 内容提供者,用于对外提供数据
b. ContentResolver.notifyChange(uri)发出消息
c. ContentResolver 内容解析者,用于获取内容提供者提供的数据
d. ContentObserver 内容监听器,可以监听数据的改变状态
e. ContentResolver.registerContentObserver()监听消息。
<script type="text/javascript"> $(function () $('pre.prettyprint code').each(function () var lines = $(this).text().split('\\n').length; var $numbering = $('<ul/>').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) $numbering.append($('<li/>').text(i)); ; $numbering.fadeIn(1700); ); ); </script>水平有限,若有错漏,欢迎指正,批评,如需转载,请注明出处–http://blog.csdn.net/vfush,谢谢!
以上是关于Android 面试题总结之Android 基础的主要内容,如果未能解决你的问题,请参考以下文章