宁波IT培训
美国上市IT培训机构

0574-87236644

Android面试题集(三)

  • 时间:2019-01-11 12:43
  • 发布:郭孝星 Open软件开发小组
  • 来源:微信公众号

描述一下Activity的生命周期,这些生命周期是如何管理的?

Activity与Fragment生命周期如下所示:

读者可以从上图看出,Activity有很多种状态,状态之间的变化也比较复杂,在众多状态中,只有三种是常驻状态:

  • Resumed(运行状态):Activity处于前台,用户可以与其交互。

  • Paused(暂停状态):Activity被其他Activity部分遮挡,无法接受用户的输入。

  • Stopped(停止状态):Activity被完全隐藏,对用户不可见,进入后台。

其他的状态都是中间状态。

我们再来看看生命周期变化时的整个调度流程,生命周期调度流程图如下所示:

所以你可以看到,整个流程是这样的:

  1. 比方说我们点击跳转一个新Activity,这个时候Activity会入栈,同时它的生命周期也会从onCreate()到onResume()开始变换,这个过程是在ActivityStack里完成的,ActivityStack 是运行在Server进程里的,这个时候Server进程就通过ApplicationThread的代理对象ApplicationThreadProxy向运行在app进程ApplicationThread发起操作请求。

  2. ApplicationThread接收到操作请求后,因为它是运行在app进程里的其他线程里,所以ApplicationThread需要通过Handler向主线程ActivityThread发送操作消息。

  3. 主线程接收到ApplicationThread发出的消息后,调用主线程ActivityThread执行响应的操作,并回调Activity相应的周期方法。

注:这里提到了主线程ActivityThread,更准确来说ActivityThread不是线程,因为它没有继承Thread类或者实现Runnable接口,它是运行在应用主线程里的对象,那么应用的主线程 到底是什么呢?从本质上来讲启动启动时创建的进程就是主线程,线程和进程处理是否共享资源外,没有其他的区别,对于Linux来说,它们都只是一个struct结构体。

Activity的通信方式有哪些?

  • startActivityForResult

  • EventBus

  • LocalBroadcastReceiver

Android应用里有几种Context对象,

Context类图如下所示:

可以发现Context是个抽象类,它的具体实现类是ContextImpl,ContextWrapper是个包装类,内部的成员变量mBase指向的也是个ContextImpl对象,ContextImpl完成了 实际的功能,Activity、Service与Application都直接或者间接的继承ContextWrapper。

描述一下进程和Application的生命周期?

一个安装的应用对应一个LoadedApk对象,对应一个Application对象,对于四大组件,Application的创建和获取方式也是不尽相同的,具体说来:

  • Activity:通过LoadedApk的makeApplication()方法创建。

  • Service:通过LoadedApk的makeApplication()方法创建。

  • 静态广播:通过其回调方法onReceive()方法的第一个参数指向Application。

  • ContentProvider:无法获取Application,因此此时Application不一定已经初始化。

Android哪些情况会导致内存泄漏,如何分析内存泄漏?

常见的产生内存泄漏的情况如下所示:

  • 持有静态的Context(Activity)引用。

  • 持有静态的View引用,

  • 内部类&匿名内部类实例无法释放(有延迟时间等等),而内部类又持有外部类的强引用,导致外部类无法释放,这种匿名内部类常见于监听器、Handler、Thread、TimerTask

  • 资源使用完成后没有关闭,例如:BraodcastReceiver,ContentObserver,File,Cursor,Stream,Bitmap。

  • 不正确的单例模式,比如单例持有Activity。

  • 集合类内存泄漏,如果一个集合类是静态的(缓存HashMap),只有添加方法,没有对应的删除方法,会导致引用无法被释放,引发内存泄漏。

  • 错误的覆写了finalize()方法,finalize()方法执行执行不确定,可能会导致引用无法被释放。

查找内存泄漏可以使用Android Profiler工具或者利用LeakCanary工具。

Android有哪几种进程,是如何管理的?

Android的进程主要分为以下几种:

前台进程

用户当前操作所必需的进程。如果一个进程满足以下任一条件,即视为前台进程:

  • 托管用户正在交互的 Activity(已调用 Activity 的 onResume() 方法)

  • 托管某个 Service,后者绑定到用户正在交互的 Activity

  • 托管正在“前台”运行的 Service(服务已调用 startForeground())

  • 托管正执行一个生命周期回调的 Service(onCreate()、onStart() 或 onDestroy())

  • 托管正执行其 onReceive() 方法的 BroadcastReceiver

通常,在任意给定时间前台进程都为数不多。只有在内存不足以支持它们同时继续运行这一万不得已的情况下,系统才会终止它们。 此时,设备往往已达到内存分页状态,因此需要终止一些前台进程来确保用户界面正常响应。

可见进程

没有任何前台组件、但仍会影响用户在屏幕上所见内容的进程。 如果一个进程满足以下任一条件,即视为可见进程:

  • 托管不在前台、但仍对用户可见的 Activity(已调用其 onPause() 方法)。例如,如果前台 Activity 启动了一个对话框,允许在其后显示上一 Activity,则有可能会发生这种情况。

  • 托管绑定到可见(或前台)Activity 的 Service。

可见进程被视为是极其重要的进程,除非为了维持所有前台进程同时运行而必须终止,否则系统不会终止这些进程。

服务进程

正在运行已使用 startService() 方法启动的服务且不属于上述两个更高类别进程的进程。尽管服务进程与用户所见内容没有直接关联,但是它们通常在执行一些用户关 心的操作(例如,在后台播放音乐或从网络下载数据)。因此,除非内存不足以维持所有前台进程和可见进程同时运行,否则系统会让服务进程保持运行状态。

后台进程

包含目前对用户不可见的 Activity 的进程(已调用 Activity 的 onStop() 方法)。这些进程对用户体验没有直接影响,系统可能随时终止它们,以回收内存供前台进程、可见进程或服务进程使用。 通常会有很多后台进程在运行,因此它们会保存在 LRU (最近最少使用)列表中,以确保包含用户最近查看的 Activity 的进程最后一个被终止。如果某个 Activity 正确实现了生命周期方法,并保存了其当前状态,则终止其进程不会对用户体验产生明显影响,因为当用户导航回该 Activity 时,Activity 会恢复其所有可见状态。

空进程

不含任何活动应用组件的进程。保留这种进程的的唯一目的是用作缓存,以缩短下次在其中运行组件所需的启动时间。 为使总体系统资源在进程缓存和底层内核缓存之间保持平衡,系统往往会终止这些进程。

ActivityManagerService负责根据各种策略算法计算进程的adj值,然后交由系统内核进行进程的管理。

SharePreference性能优化,可以做进程同步吗?

在Android中, SharePreferences是一个轻量级的存储类,特别适合用于保存软件配置参数。使用SharedPreferences保存数据,其背后是用xml文件存放数据,文件 存放在/data/data/ < package name > /shared_prefs目录下.

之所以说SharedPreference是一种轻量级的存储方式,是因为它在创建的时候会把整个文件全部加载进内存,如果SharedPreference文件比较大,会带来以下问题:

  1. 第一次从sp中获取值的时候,有可能阻塞主线程,使界面卡顿、掉帧。

  2. 解析sp的时候会产生大量的临时对象,导致频繁GC,引起界面卡顿。

  3. 这些key和value会永远存在于内存之中,占用大量内存。

优化建议

  1. 不要存放大的key和value,会引起界面卡、频繁GC、占用内存等等。

  2. 毫不相关的配置项就不要放在在一起,文件越大读取越慢。

  3. 读取频繁的key和不易变动的key尽量不要放在一起,影响速度,如果整个文件很小,那么忽略吧,为了这点性能添加维护成本得不偿失。

  4. 不要乱edit和apply,尽量批量修改一次提交,多次apply会阻塞主线程。

  5. 尽量不要存放JSON和HTML,这种场景请直接使用JSON。

  6. SharedPreference无法进行跨进程通信,MODE_MULTI_PROCESS只是保证了在API 11以前的系统上,如果sp已经被读取进内存,再次获取这个SharedPreference的时候,如果有这个flag,会重新读一遍文件,仅此而已。

    文章转载于作者郭孝星 Open软件开发小组

    有兴趣的小伙伴可以关注我们日后的干货分享哦!当然,你想了解更多关于面试的知识,
    可以填写下方的表单,有利于咨询老师更快的找到你哦!我们下次见~

预约申请免费试听课

怕钱不够?就业挣钱后再付学费!    怕学不会?从入学起,达内定制课程!     担心就业?达内多家实践企业供你挑选!

上一篇:Android面试题集(二)
下一篇:Android面试题集(四)

2020年Web前端面试问题总结之JS问题

2020年Web前端面试问题总结之VUE问题

2020年Web前端面试问题总结之React问题

2020年Web前端笔试题汇总

选择城市和中心
江西省

贵州省

广西省

海南省