Android中高级进阶开发面试题冲刺合集(三)

以下主要针对往期收录的面试题进行一个分类归纳整理,方便大家统一回顾和参考。本篇是第三集~

强调一下:【因篇幅问题:文中只放部分内容,全部文档需要的可找作者获取。

第一篇面试题在这: Android中高级进阶开发面试题冲刺合集(一)

第二篇面试题在这: Android中高级进阶开发面试题冲刺合集(二)

Android 方面

Android 考察点比较纷杂,以下针对之前收录的面试题做一个大概的划分:

Android 四大组件相关

1.Activity 与 Fragment 之间常见的几种通信方式?

参考答案:

1、对于Activity和Fragment之间的相互调用 (1)Activity调用Fragment 直接调用就好,Activity一般持有Fragment实例,或者通过Fragment id 或者tag获取到Fragment实例 (2)Fragment调用Activity 通过activity设置监听器到Fragment进行回调,或者是直接在fragment直接getActivity获取到activity实例 2、Activity如果更好的传递参数给Fragment 如果直接通过普通方法的调用传递参数的话,那么在fragment回收后恢复不能恢复这些数据。google给我们提供了一个方法 setArguments(bundle) 可以通过这个方法传递参数给fragment,然后在fragment中用getArguments获取到。能保证在fragment销毁重建后还能获取到数据

2.谈谈 Android 中几种 LaunchMode 的特点和应用场景?

参考答案:

LaunchMode 有四种,分别为 StandardSingleTopSingleTaskSingleInstance,每种模式的实现原理一楼都做了较详细说明,下面说一下具体使用场景:

  • Standard: Standard 模式是系统默认的启动模式,一般我们 app 中大部分页面都是由该模式的页面构成的,比较常见的场景是:社交应用中,点击查看用户A信息->查看用户A粉丝->在粉丝中挑选查看用户B信息->查看用户A粉丝… 这种情况下一般我们需要保留用户操作 Activity 栈的页面所有执行顺序。
  • SingleTop: SingleTop 模式一般常见于社交应用中的通知栏行为功能,例如:App 用户收到几条好友请求的推送消息,需要用户点击推送通知进入到请求者个人信息页,将信息页设置为 SingleTop 模式就可以增强复用性。
  • SingleTask: SingleTask 模式一般用作应用的首页,例如浏览器主页,用户可能从多个应用启动浏览器,但主界面仅仅启动一次,其余情况都会走onNewIntent,并且会清空主界面上面的其他页面。
  • SingleInstance: SingleInstance 模式常应用于独立栈操作的应用,如闹钟的提醒页面,当你在A应用中看视频时,闹钟响了,你点击闹钟提醒通知后进入提醒详情页面,然后点击返回就再次回到A的视频页面,这样就不会过多干扰到用户先前的操作了。

3.BroadcastReceiver 与 LocalBroadcastReceiver 有什么区别?

参考答案:

  • BroadcastReceiver 是跨应用广播,利用Binder机制实现,支持动态和静态两种方式注册方式。
  • LocalBroadcastReceiver 是应用内广播,利用Handler实现,利用了IntentFilter的match功能,提供消息的发布与接收功能,实现应用内通信,效率和安全性比较高,仅支持动态注册。

4.对于 Context,你了解多少?

参考答案:

  1. 在 Android 平台上 , Context 是一个基本的概念,它在逻辑上表示一个运行期的“上下文”
  2. Context 体现到代码上来说,是个抽象类,其主要表达的行为有:使用系统提供的服务、访问资源 、信息 存储相关以及AMS的交互
  3. 在 Android 平台上,Activity、Service 和 Application 在本质上都是个 Context
  4. Android 中上下文访问应用资源或系统服务的动作都被统一封装进 ContextImpl 类中.Activity、 Service、Application 内部都含有自己的 ContextImpl,每当自己需要访问应用资源或系统服务时,就是 把请求委托给内部的 ContextImpl
  5. ContextWrapper 为 Context 的包装类, 它在做和上下文相关的动作时,基本上都是委托给 ContextImpl 去做
  6. ContextImpl 为一个上下文的核心部件,其负责和Android平台进行通信. 就以启动 activity 动作来说,最后 会走到 ContextImpl 的 startActivity(),而这个函数内部大体上是进一步调用 mMainThread.getInstrumentation().execStartActivity(),从而将语义发送给Android系统
  7. Context数量 = Activity数量 + Service数量 + 1 上面的1表示 Application 数量,一个应用程序里面可以有多个 Application,可是在配置文件 AndroidManifest.xml中只能注册一个, 只有注册的这个 Application 才是真正的 Application

5.IntentFilter 是什么?有哪些使用场景?匹配机制是怎样的?

参考答案:

1.IntentFilter是意图过滤器,常用于Intent的隐式调用匹配。 2.IntentFilter有3种匹配规则,分别是action、categroy、data。

action的匹配原则: IntentFilter可以有多个action,Intent最多能有1个。 1.如果IntentFilter中不存在action,那么所有的intent都无法通过。 2.如果IntentFilter存在action。 a.如果intent不存在,那么可以通过。 b.如果intent存在,那么intent中的action必须是IntentFilter中的其中一个,对比区分大小写。

category的匹配原则: IntentFilter可以有多个category,Intent也可以有多个。 1.如果IntentFilter不存在category,那么所有的intent都无法通过,因为隐式调用的时候,系统默认给Intent附加了“android.intent.category.DEFAULT”。 2.如果IntentFilter存在category a.如果intent不存在,可以通过。 b.如果intent存在,那么intent中的所有category都包含在IntentFilter中,才可以通过。

data的匹配原则: IntentFilter可以有多个data,Intent最多能有1个。 IntentFilter和Intent完全匹配才能通过,也适用于通配符。

匹配规则: Intent需要匹配多组intent-fliter中的任意一组,每一组包含action、data、category,即Intent必须同时满足这三者的过滤规则。 在同一个应用中,尽量使用显示意图,因为显示意图比隐式意图的效率高。

6.谈一谈 startService 和 bindService 方法的区别,生命周期以及使用场景?

参考答案:

1、生命周期上的区别

执行startService时,Service会经历onCreate->onStartCommand。当执行stopService时,直接调用onDestroy方法。调用者如果没有stopService,Service会一直在后台运行,下次调用者再起来仍然可以stopService。
​
执行bindService时,Service会经历onCreate->onBind。这个时候调用者和Service绑定在一起。调用者调用unbindService方法或者调用者Context不存在了(如Activity被finish了),Service就会调用onUnbind->onDestroy。这里所谓的绑定在一起就是说两者共存亡了。
​
多次调用startService,该Service只能被创建一次,即该Service的onCreate方法只会被调用一次。但是每次调用startService,onStartCommand方法都会被调用。Service的onStart方法在API 5时被废弃,替代它的是onStartCommand方法。
​
第一次执行bindService时,onCreate和onBind方法会被调用,但是多次执行bindService时,onCreate和onBind方法并不会被多次调用,即并不会多次创建服务和绑定服务。

2、调用者如何获取绑定后的Service的方法

onBind回调方法将返回给客户端一个IBinder接口实例,IBinder允许客户端回调服务的方法,比如得到Service运行的状态或其他操作。我们需要IBinder对象返回具体的Service对象才能操作,所以说具体的Service对象必须首先实现Binder对象。

3、既使用startService又使用bindService的情况

如果一个Service又被启动又被绑定,则该Service会一直在后台运行。首先不管如何调用,onCreate始终只会调用一次。对应startService调用多少次,Service的onStart方法便会调用多少次。Service的终止,需要unbindService和stopService同时调用才行。不管startService与bindService的调用顺序,如果先调用unbindService,此时服务不会自动终止,再调用stopService之后,服务才会终止;如果先调用stopService,此时服务也不会终止,而再调用unbindService或者之前调用bindService的Context不存在了(如Activity被finish的时候)之后,服务才会自动停止。
​
那么,什么情况下既使用startService,又使用bindService呢?
​
如果你只是想要启动一个后台服务长期进行某项任务,那么使用startService便可以了。如果你还想要与正在运行的Service取得联系,那么有两种方法:一种是使用broadcast,另一种是使用bindService。前者的缺点是如果交流较为频繁,容易造成性能上的问题,而后者则没有这些问题。因此,这种情况就需要startService和bindService一起使用了。
​
另外,如果你的服务只是公开一个远程接口,供连接上的客户端(Android的Service是C/S架构)远程调用执行方法,这个时候你可以不让服务一开始就运行,而只是bindService,这样在第一次bindService的时候才会创建服务的实例运行它,这会节约很多系统资源,特别是如果你的服务是远程服务,那么效果会越明显(当然在Servcie创建的是偶会花去一定时间,这点需要注意)。    

4、本地服务与远程服务

本地服务依附在主进程上,在一定程度上节约了资源。本地服务因为是在同一进程,因此不需要IPC,也不需要AIDL。相应bindService会方便很多。缺点是主进程被kill后,服务变会终止。
​
远程服务是独立的进程,对应进程名格式为所在包名加上你指定的android:process字符串。由于是独立的进程,因此在Activity所在进程被kill的是偶,该服务依然在运行。缺点是该服务是独立的进程,会占用一定资源,并且使用AIDL进行IPC稍微麻烦一点。
​
对于startService来说,不管是本地服务还是远程服务,我们需要做的工作都一样简单。

7.Service 如何进行保活?

参考答案:

1:跟各大系统厂商建立合作关系,把App加入系统内存清理的白名单

2:白色保活

用startForeground()启动前台服务,这是官方提供的后台保活方式,不足的就是通知栏会常驻一条通知,像360的状态栏。

3:灰色保活

开启前台Service,开启另一个Service将通知栏移除,其oom_adj值还是没变的,这样用户就察觉不到app在后台保活。 用广播唤醒自启,像开机广播、网络切换广播等,但在国产Rom中几乎都被堵上了。 多个app关联唤醒,就像BAT的全家桶,打开一个App的时候会启动、唤醒其他App,包括一些第三方推送也是,对于大多数单独app,比较难以实现。

4:黑色保活

1 像素activity保活方案,监听息屏事件,在息屏时启动个一像素的activity,提升自身优先级; Service中循环播放一段无声音频,伪装音乐app,播放音乐中的app优先级还是蛮高的,也能很大程度保活效果较好,但耗电量高,谨慎使用; 双进程守护,这在国产rom中几乎没用,因为划掉app会把所有相关进程都杀死。 3、实现过程:

1)、用startForeground()启动前台服务

前台Service,使用startForeground这个Service尽量要轻,不要占用过多的系统资源,否则系统在资源紧张时,照样会将其杀死。

DaemonService.java

可以参考下面的 Android实现进程保活方案解析

8.简单介绍下 ContentProvider 是如何实现数据共享的?

参考答案:

当一个应用程序要把自己的数据暴露给其他程序时,可以通过ContentProvider来实现。 其他应用可以通过ContenrResolver来操作ContentProvider暴露的数据。

如果应用程序A通过ContentProvider暴露自己的数据操作接口,那么不管A 是否启动,其他程序都可以通过该接口来操作A的内部数据,常有增、删、查、改。

ContentProvider是以Uri的形式对外提供数据,ContenrResolver是根据Uri来访问数据。

步骤

定义自己的ContentProvider类,该类需要继承Android系统提供的ContentProvider基类。

在Manifest.xml 文件中注册ContentProvider,(四大组件的使用都需要在Manifest文件中注册) 注册时需要绑定一个URL。

例如: android:authorities=“com.myit.providers.MyProvider” 说明:authorities就相当于为该ContentProvider指定URL。 注册后,其他应用程序就可以通过该Uri来访问MyProvider所暴露的数据了。 其他程序使用ContentResolver来操作。

调用Activity的ContentResolver获取ContentResolver对象 调用ContentResolver的insert(),delete(),update(),query()进行增删改查。 一般来说,ContentProvider是单例模式,也就是说,当多个应用程序通过ContentResolver来操作ContentProvider提供的数据时,ContentResolver调用的数据操作将会委托给同一个ContentResolver。

9.说下切换横竖屏时 Activity 的生命周期变化?

参考答案:

竖屏: 启动:onCreat->onStart->onResume. 切换横屏时: onPause-> onSaveInstanceState ->onStop->onDestory

onCreat->onStart->onSaveInstanceState->onResume.

但是,我们在如果配置这个属性:android:configChanges=“orientation|keyboardHidden|screenSize” 就不会在调用Activity的生命周期,只会调用onConfigurationChanged方法

10.Activity 中 onNewIntent 方法的调用时机和使用场景?

参考答案:

Activity 的 onNewIntent方法的调用可总结如下:

在该Activity的实例已经存在于Task和Back stack中(或者通俗的说可以通过按返回键返回到该Activity )时,当使用intent来再次启动该Activity的时候,如果此次启动不创建该Activity的新实例,则系统会调用原有实例的onNewIntent()方法来处理此intent.

且在下面情况下系统不会创建该Activity的新实例:

1,如果该Activity在Manifest中的android:launchMode定义为singleTask或者singleInstance.

2,如果该Activity在Manifest中的android:launchMode定义为singleTop且该实例位于Back stack的栈顶.

3,如果该Activity在Manifest中的android:launchMode=“singleInstance”,或者intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)标志.

4,如果上述intent中包含 Intent.FLAG_ACTIVITY_CLEAR_TOP 标志和且包含 Intent.FLAG_ACTIVITY_SINGLE_TOP 标志.

5,如果上述intent中包含 Intent.FLAG_ACTIVITY_SINGLE_TOP 标志且该实例位于Back stack的栈顶.

上述情况满足其一,则系统将不会创建该Activity的新实例.

根据现有实例所处的状态不同onNewIntent()方法的调用时机也不同,总的说如果系统调用onNewIntent()方法则系统会在onResume()方法执行之前调用它.这也是官方API为什么只说"you can count on onResume() being called after this method",而不具体说明调用时机的原因.

11.Intent 传输数据的大小有限制吗?如何解决?

参考答案:

先说结论:

有大小限制

再说原因:

Intent 是消息传递对象,用于各组件间通信。各组件以及个程序间通信都用到了进程间通信。因此 Intent 的数据传递是基于 Binder 的,Intent 中的数据会存储在 Bundle 中,然后 IPC 过程中会将各个数据以 Parcel 的形式存储在 Binder 的事物缓冲区(Binder transaction buffer)进程传递,而 Binder 的事物缓冲区有个固定的大小,大小在 1M 附近。因为这 1M 大小是当前进程共享的,Intent 中也会带有其他相关的必要信息,所以实际使用中比这个数字要小很多。

解决方式:

  1. 降低传递数据的大小,或考虑其他方式,见2;
  2. IPC: 将大数据缓存到文件,或者存入数据库,或者图片使用 id 等;使用 Socket;
  3. 非 IPC:可以考虑共享内存,EventBus 等

12.说说 ContentProvider、ContentResolver、ContentObserver 之间的关系?

参考答案:

ContentProvider * 内容提供者, 用于对外提供数据,比如联系人应用中就是用了ContentProvider, * 一个应用可以实现ContentProvider来提供给别的应用操作,通过ContentResolver来操作别的应用数据

ContentResolver * 内容解析者, 用于获取内容提供者提供的数据 * ContentResolver.notifyChange(uri)发出消息

ContentObserver * 内容监听者,可以监听数据的改变状态 * 观察(捕捉)特定的Uri引起的数据库的变化 * ContentResolver.registerContentObserver()监听消息

概括: 使用ContentResolver来获取ContentProvider提供的数据, 同时注册ContentObserver监听数据的变化

13.说说 Activity 加载的流程?

参考答案:

App 启动流程(基于Android8.0):

  • 点击桌面 App 图标,Launcher 进程采用 Binder IPC(具体为ActivityManager.getService 获取 AMS 实例) 向 system_server 的 AMS 发起 startActivity 请求
  • system_server 进程收到请求后,向 Zygote 进程发送创建进程的请求;
  • Zygote 进程 fork 出新的子进程,即 App 进程
  • App 进程创建即初始化 ActivityThread,然后通过 Binder IPC 向 system_server 进程的 AMS 发起 attachApplication 请求
  • system_server 进程的 AMS 在收到 attachApplication 请求后,做一系列操作后,通知 ApplicationThread bindApplication,然后发送 H.BIND_APPLICATION 消息
  • 主线程收到 H.BIND_APPLICATION 消息,调用 handleBindApplication 处理后做一系列的初始化操作,初始化 Application 等
  • system_server 进程的 AMS 在 bindApplication 后,会调用 ActivityStackSupervisor.attachApplicationLocked,之后经过一系列操作,在 realStartActivityLocked 方法通过 Binder IPC 向 App 进程发送 scheduleLaunchActivity 请求;
  • App进程的 binder 线程(ApplicationThread)在收到请求后,通过 handler 向主线程发送 LAUNCH_ACTIVITY 消息;
  • 主线程收到 message 后经过 handleLaunchActivity,performLaunchActivity 方法,然后通过反射机制创建目标 Activity;
  • 通过 Activity attach 方法创建 window 并且和 Activity 关联,然后设置 WindowManager 用来管理 window,然后通知 Activity 已创建,即调用 onCreate
  • 然后调用 handleResumeActivity,Activity 可见

补充:

  • ActivityManagerService 是一个注册到 SystemServer 进程并实现了 IActivityManager 的 Binder,可以通过 ActivityManager 的 getService 方法获取 AMS 的代理对象,进而调用 AMS 方法
  • ApplicationThread 是 ActivityThread 的内部类,是一个实现了 IApplicationThread 的 Binder。AMS通过 Binder IPC 经 ApplicationThread 对应用进行控制
  • 普通的 Activity 启动和本流程差不多,至少不需要再创建 App 进程了
  • Activity A 启动 Activity B,A 先 pause 然后 B 才能 resume,因此在 onPause 中不能做耗时操作,不然会影响下一个 Activity 的启动
Android 异步任务和消息机制

1.HandlerThread 的使用场景和实现原理?

参考答案&

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: MySQL高级进阶面试题是指那些更加深入和复杂的MySQL面试题,涉及到MySQL的高级特性和性能优化等方面。这些问题需要对MySQL的内部原理和工作机制有一定的了解。根据引用\[1\]中提到的MySQL面试题大全,这套面试题包含了大量经典的MySQL程序员面试题以及答案,涵盖了MySQL语言常见面试题、MySQL工程师高级面试题以及一些大厂MySQL开发面试宝典等内容。对于应届生、实习生和有工作经验的人来说,都可以参考学习这套面试题,以提升自己的MySQL技能和面试竞争力。 在MySQL高级进阶面试题中,可能会涉及到一些具体的SQL语句和执行过程。例如,引用\[2\]中提到的一个SQL语句"select * from user where id > 1 and name = '大彬'",在执行这个语句之前,会先检查权限,然后进行词法分析和语法分析,提取表名和查询条件,检查语法是否有错误。接下来,优化器会根据自己的优化算法选择执行效率最好的执行方案。最后,校验权限并调用数据库引擎接口,返回引擎的执行结果。 此外,引用\[3\]中提到了一些关于使用SELECT...FOR UPDATE语句的注意事项,例如该语句仅适用于InnoDB引擎,并且必须在事务范围内才能生效。还提到了在查询过程中可能会产生表锁的情况,如根据主键进行查询时,查询条件为like或者不等于,或者根据非索引字段进行查询。 对于大表的优化,可以采取一些措施来提升性能,例如合理设计索引、分区表、使用查询缓存、优化查询语句等。具体的优化策略需要根据具体情况进行分析和调整。 总之,MySQL高级进阶面试题涵盖了MySQL的高级特性和性能优化等方面的知识,对于想要深入了解和掌握MySQL的人来说,这些面试题是很有价值的学习资料。 #### 引用[.reference_title] - *1* [经典 55道 MySQL面试题及答案](https://blog.csdn.net/Firstlucky77/article/details/124967594)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [史上最强MySQL高频面试题](https://blog.csdn.net/q1472750149/article/details/121594014)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值