Android 四大组件流程、Handler、AsyncTask、IntentService相关面试知识点(三)

一、activity生命周期

  1. 什么是activity?

    • Android中的四大组件,用来于用户交互的组件,利用setContentView可以来显示组件

  2. activity的四种状态

    • running (activity处于栈顶)/paused(失去焦点)/stopped/killed

  3. activity生命周期

    • onCreate 正在创建,常做初始化工作

    • onStart 正在启动,这时activity可见但不在前台,无法和用户交互

    • onResume 获得焦点,此时activity可见且在前台并开始活动

    • onPause activity正在停止,可做数据存储、停止动画操作

    • onStop 即将停止,可做稍微重量级回收工作,如取消网络连接、注销广播接收器等

    • onDestory activity即将销毁,常做回收工作、资源释放

    • 当activity由后台切换到前台,由不可见到可见时会调用onRestart,activity重新启动

  4. onStart() 和onResume 与onPause()和onStop()得区别?

    • onStart()和onStop()是从Activity是否可见角度调用的

    • onResume()和onPause()是从Activity是否在前台这个角度回调的,实际中没其它明显区别

  5. Activity A启动B回调的方法有?

    • A onPause -> B onCreate -> B onStart -> B onResume -> A onStop

    • 如果B是完全透明或者对话框,则不会调用A onStop

  6. onSaveInstanceState()方法,何时调用?

    • 非人为终止Activity时,比如系统配置发生改变导致Activity被杀死并重新创建、资源内存不足导致低优先级的Activity被杀死,会调用onSaveInstanceState()来保存状态,该方法调用在onStop之前

    • 恢复数据时,一般在onRestoreInstanceState()方法,一般在onStart之后调用

  7. onSaveInstanceState()和onPause的区别?

    • onSaveInstanceState()适用于对临时性状态的保存,而onPause()适用于对数据的持久化保存

  8. activity任务栈

    • Task,栈结构,后进先出,用于存放Activity组件,例如默认模式下,A启动B,那么A的栈定是Activity B

  9. activity启动模式

    • standard 标准模式,每次启动一个Activity就会创建一个新实例

    • singleTop 栈顶复用模式,新Activity在任务栈栈顶,就不会创建,并回调onNewIntent()方法,如果不在则新建

    • singleTask 栈内复用模式,任务栈内有该Activity实例,就会移除该activity栈顶activity,并回调onNewIntent()方法,不存在则会新建该实例

    • singleInstance 单实例模式,此模式的Activity只能单独位于一个任务栈中,且只有唯一一个实例

    • singleTop可重复创建实例,不会引起任务栈的变更,防止多次快速点击启动activity,可以将activity设置为singleTop,singleTask可以利用taskAffinity指定任务栈,一般用于登录页

  10. Activity的启动过程

    • Activity的startActivity到Instrumenation的execStartActivity,再利用Binder进程通信,调用AMS的startActivity,中间经过一些流程最终会到ActivityThread内部类ApplicationThread的scheduleLaunchActivity,然后将启动Activity的消息发送交给ActivityThread的Handler类H处理,handleLaunchActivity()再调用performLaunchActivity()

  11. scheme跳转协议

    • 页面内跳转协议,方便APP页面内的跳转

    • 服务端下发跳转路径,H5点击描点,根据描点具体跳转路径APP的具体页面

    • 在清单文件的intent-filter中进行data配置,host:代表scheme作用于哪个地址域,port代表该路径的端口号,path代表scheme指定的页面,还可以携带参数

二、Fragment 第五大组件

  1. Fragment的生命周期(起初是为了给大屏幕展现UI设计的,Android 3.0)

    • onAttach -> onCreate -> onCreateView -> onViewCreated -> Activity : onCreate -> onActivityCreated -> Activity : onStart -> onStart -> Activity : onResume -> onResume -> onPause -> Activity : onPause -> onStop -> Activity : onStop -> onDestroyView -> onDestroy -> onDetach -> Activity : onDestroy

  2. 加载方式

    • 添加到布局

    • 动态在activity中添加

  3. FragmentPagerAdapter和FragmentStatePagerAdapter的区别?

    • 从源码角度看,FragmentPagerAdaper在destroyItem中仅仅是detach fragment,解绑视图,而FragmentStatePagerAdapter是remove Fragment,所以前者适合界面少的应用,后者适合界面多的应用

  4. Fragment通信

    • 与Activity通信,推荐谷歌官方做法,接口回调方法

    • 可以使用EventBus或者findFragmentById做法

  5. Activity和Fragment的区别

    • 两者都包含布局

    • 但是Fragment依附在Activity上的,多了和宿主Activity相关的生命周期方法,例如onAttach、onDetach等,并且Fragment的生命周期方法是由宿主Activity调用的,而不是系统,从生命周期修饰符可以印证,Activity的都是protected,而Fragment的是public

    • 我们可以在Activity中动态替换、移除Fragment

    • Activity的FragmentManager负责用来调用队列中Fragment的生命周期方法,和Activity同步状态

    • 单一场景,切换时更适合用Fragment,或者模块化中,一个Fragment对应一个模块。

三、Service

  1. Service是什么?

    • 一种长生命周期,无可视化界面,运行于后台的一种服务程序

  2. Service与Thread的区别

    • service运行在主线程中,不能执行耗时操作,主线程难以控制Thread,当Activity销毁后,是没有办法获取之前的Thread的,如果Thread内的run方法没有执行完毕,它会一直执行

  3. 两种启动方式的生命周期

    • onCreate -> onStartCommand -> onDestroy

    • onCreate -> onBind -> onUnbind -> onDestroy

  4. Service的启动方式

    • startService onCreate -> onStartCommand 后一直保持运行,如果服务已经开了,仅仅是会调用onStartCommand方法,无论startService调用了多少次,只需要调用一次stopService就会停止

    • bindService onCreate -> onBind,只要服务没断开就可以一直通信

  5. 两种启动方式的工作流程

    • startService 会调用ContextImpl的startServiceCommon,然后通过Binder机制与AMS通信,调用AMS的startService方法,最后调用ApplicationThread的scheduleCreateService,然后在发送消息交由ActivityThread的Handle类H处理,调用handleCreateService、handleServiceArgs,这两个方法内分别调用了service的onCreate和onStartCommand方法

    • bindService 会调用bindServiceCommon方法,然后与AMS通信,调用bindService方法,同样最后会调用ApplicationThread的scheduleCreateService方法,然后发送消息交由H处理,调用handCreateService方法,然后会调用ApplicationThread的scheduleBindService方法,发送消息交给H处理,调用handBindService,然后会调用AMS的publishService方法,最后会调用ServiceConnection的onServiceConnected方法

  6. 如何保证Service不杀死

    • 增加Service优先级,例如设置为一个前台服务

    • 如果是startService的话,直接在onStartCommand的返回值改为START_STICKY,每次被杀死后都会再次启动

    • 当然还可以再onDestroy发送广播,然后onReceive中启动Service

  7. 一些系统常见的Service

    • WINDOW_SERVICE 管理打开窗口程序 WindowManager

    • ACTIVITY_SERVICE 管理应用程序 ActivityManager 对应的ActivityManagerService,负责四大组件的启动、切换、调度和进程管理等作用

    • ALARM_SERVICE 闹钟服务 AlarmManager 例如它的定时服务,定层也是通过handler实现的

四、BroadcastReceiver

  1. 广播的定义

    • 类似一个全局的监听器,属于Android四大组件,优点观察者模式的味道

    • 不同APP或者同一APP间多个进程的不同组件通信

    • 静态注册完成后将一直运行,进程杀死还在运行

  2. 广播的种类

    • 普通广播

    • 有序广播,可以称为系统广播

    • 本地广播,只在APP内传播,利用LocalBroadcastManager类

  3. 有序广播的工作流程

    • 注册的话,直接通过AMS,调用其registerReceiver

    • 调用ContextImpl的sendBroadcast,将消息放到BroadcastQueue中,然后再发送消息交由BroadcastHandler处理,最后会调用ApplicationThread的scheduleRegisteredReceiver,最后会调用LoadedApk内部类ReceiverDispatcher的performReceive,进而调用receiver.onReceive方法

五、ContentProvider

  1. 什么是ContentProvider?

    • ContentProvider是不同应用程序之间进行交换数据的标准API,主要负责存储和共享数据

    • Android内置的许多数据都是使用ContentProvider形式,供开发者调用的,如音频、图片、通讯录

  2. ContentProvider工作流程

    • 使用ContentResolver的query来说,调用query方法,它会调用ApplicationContentResolver的acquireUnstableProvider方法,继而调用ActivityThread的acquireProvider方法,然后与AMS通信,调用其getContentProvider方法,接下来会调用Process.start方法开启一个进程,运行ActivityThread的main方法,再调用AMS的attachApplication方法,最后会经由ActivityThread的H处理,调用handleBindApplication,再调用installContentProviders方法。

  3. 与SharePreferencs的区别?

    • SP是一种轻量级的数据存储方式,一般用来存储简单的配置信息,基于xml文件的KEY-VALUE数据

    • 保存的数据仅能被本应用使用,而CP则能被不同应用使用

    • SP的读写有一定的缓存策略,在内存中有一份该文件的缓存,在多进程模式下,读写会很不可靠,可能会丢失数据

  4. 与SQLite的区别?

    • 轻量级关系型数据库,占用资源少,存储大量数据时可以使用

    • 批量操作可以利用SQLiteStatement操作,开启事务和结束事务

    • SQLite使用完得注意及时关闭Cursor,读取数据库属于耗时操作

    • 使用索引加快检索进度

    • 创建好的表,不允许修改和删除表字段,除非赋值新表保留想要的字段

六、WebView

  1. Android API16之前的版本存在远程代码执行安全漏洞,该漏洞源于程序没有正确限制使用WebView.addJavascriptInterface接口,远程攻击者可以通过使用Java Reflection API利用该漏洞执行任意JAVA对象的方法

  2. WebView内存泄露

    • 记得及时remove WebView,再将webview onDestroy

    • WebView方法一个独立进程,减轻负担

    • 动态创建WebView的时候,对传入WebView的Content使用弱引用。Activity创建时add,onDestroy时remove

  3. WebViewClient.onPageFinished调用多次,采用WebChromeClient.onProgressChanged方法替换

  4. 后台耗电问题

    • 直接System.exit(0)将虚拟机退出,暴力解决或其他好的方法

七、Binder

  1. 为什么要多进行多进程间通信,也就是IPC

    • 不同进程的四大组件的运行,依赖于IPC机制,它们之间需要通过内存共享数据,每个进程相当于一个独立的虚拟机,不同的虚拟机在内存分配上地址空间不同,不同虚拟机访问同一个类对象会出现很多副本的

    • 多进程可使SharedPreference不可靠性增加,数据丢失率有一定的增加,Application创建多个,静态变量和单例模式失效

  2. 序列化

    • Serializable 简单、效率低、开销大。适合将对象序列化到存储设备,或者将对象序列化后通过网络传输

    • Parcelable 高效、使用相对复杂。主要用在内存序列化上。使用IBinder作为载体,直接在内存上读写

  3. 为什么用Binder来所谓主要的IPC通信方式?

    • Android使用的Linux内核拥有着非常多的跨进程通信

    • 传输效率高,可操作性强。前者是指内存拷贝次数,一般的通信,都是先从发送方的缓存区拷贝到内核开辟的缓存区,再从内核缓存区拷贝到接受方的缓存区。有两次拷贝。而Binder,只需要将数据从发送方的缓存区拷贝到内核的缓存区,接收方的缓存区与内核的缓存区是映射到同一块物理地址的。

    • 实现C/S架构方便。Binder基于C/S架构,Server端和Client端相对独立,稳定性好。

    • 安全性高。例如Socket通信,IP地址可以人为修改,而Binder机制为每个进程分配了UIP/PID,在通信时会进行校验

  4. Binder进行数据传输的具体过程

    • 服务端返回Binder对象,客户端通过AIDL接口asInterface()得到Binder对象(不同进程是代理Binder),通过得到的Binder类发起RPC请求,客户端挂起当前线程,将参数写入到data,然后调用transact方法,RPC请求通过底层封装后交由服务端的onTransact方法处理,将结果写入到reply,最后返回结果并唤醒客户端线程。

  5. Binder驱动

    • 例如A通过通讯录给B打电话,号码通过通讯录获取,两者通信必须依靠电话基站,这个相当于Binder驱动,通讯录相当于ServiceManager

    • 两个运行在用户空间的进程要完成通信,必须依靠于内核的帮助,而这个运行在内核的程序就是Binder驱动

    • Service在ServiceManager中注册,Client通过名字去ServiceManager中查找,返回查找的Binder对象,然后拿到Binder后调用Service方法

  6. 如何优化多模块使用AIDL的情况

    • 如果为每个模块创建特定的AIDL文件,那么相对应的Service就会很多,会出现资源耗损严重等情况,这时候就应该使用Binder连接池解决。Server端提供一个queryBinder接口,不同业务模块拿到不同的Binder对象就可以使用了,Binder连接池的作用主要是将每个业务模块的Binder请求统一转发到远程Service执行。

八、Handler

  1. 什么是handler

    • 主线程更新UI,子线程不能更新UI,利用Handler可以灵活更新UI

    • handler post(runnable)方法,sendMessage(message)方法,最后调用的都是sendMessageAtTime方法

  2. Handler内部机制

    • sendMessage把消息和Handler通过MeesageQueeu的enqueueMessage方法传给MessageQueue,也就是所谓的把消息放入到消息队列中,然后通过Looper的next方法处理信息,调用handler的dispatchMessage方法,最后回调handMessage方法

  3. Handler引起的内存泄露以及解决办法

    • 静态内部类持有外部类的匿名引用,导致外部Activity无法释放

    • 解决办法:handler内部持有外部activity的弱引用,并把Handler改为静态类,或者在activity的onDestroy中调用removeCallback

九、AsyncTask

  1. 什么是AsyncTask

    • 它本质上是一个封装了线程池和handler的异步框架

  2. 需要注意事项上篇有提及,主要就是新建AsyncTask需要在主线程中执行

  3. AsyncTask机制原理

    • 上篇也有提,这里做个小结。

    • AsyncTask的本质是一个静态的线程池,AsyncTask派生出的子类可以实现不同的异步任务,这些任务默认都是排队提交到静态的线程池中执行的

    • 线程池的工作线程会执行doInBackground(mParams)方法执行异步任务

    • 当任务状态改变后,工作线程会向UI线程发送消息,AsyncTask内部的InternalHandler响应这些消息并调用相关的回调函数

  4. 内存泄露问题

    • 和handler类似,改成静态类

    • 最好在onDestroy时cancel

十、HandlerThread

  1. HandlerThread是什么?

    • 开启Thread子线程进行耗时操作,多次创建和销毁是很耗系统资源的

    • 本质是handler + thread + looper,thread 内部有looper

    • HanderlThread继承了Thread,有自己内部的Looper对象,可以进行Looper循环

    • 通过HandlerThread的looper对象传递Handler,在handleMessage方法中执行异步任务

    • 优点是不会有堵塞,减少了对性能的消耗,缺点是不能同时进行多任务处理,属于串行

  2. HandlerThread机制

    • 在run方法里,通过Looper.prepare和Looper.loop开启了消息循环,然后将Handler传递给Looper,在Looper.loop内会调用handler的dispatchMessage方法,然后会调用传递的callback或者是handlerMessage方法处理消息

十一、IntentService

  1. IntentService是什么?

    • IntentService是继承并处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动方式和传统的一样,当任务执行完毕后,内部会调用stopSelf(id)类自动停止,可以启动IntentService多次,而每一个耗时操作会以工作队列的方式在IntentService的onHandleIntent回调方法中执行,并且,每次指挥执行一个工作线程,执行完后再执行第二个

    • 本质是通过HandlerThread和Handler实现异步操作

    • 是一种特殊的Service,继承自Service

  2. IntentService原理机制

    • 在它的onCreate中会初始化一个HandlerThrad和ServiceHandler,然后在onStart方法内会将intent封装成Message,利用ServiceHandler发送出去,经由自己的handleMessage处理,最后会调用onHandleIntent方法

你可能感兴趣的:(Android进阶)