高级Android面试(一) :基础相关面试

板块一:Activity

activity的生命周期

(1) activity的四种状态
running/paused/stopped/killed

活动状态(running)

活动状态一般是指该Activity正处于屏幕最显著的位置上显示,即该Activity是在Android活动栈的最顶端。
一般地当Activity 创建后就是处于该状态中。
期间触发的函数及顺序为: onCreate() ->onStart() -> onResume()。
其中:
onCreate()只有在该Activity是第一次被创建时才会被调用,主要是负责Activity的一般性的初始化设置,包括视图的创建,数据的绑定等等。需要注意的是若之前有冻结的state(即系统对该Activity调用过onSaveInstanceState()函数),则可以通过其 Bundle 参数进行state恢复。
onStart()是当Activity正在变为可见状态时才会被调用。一般地在此期间可以注册一个广播等等。
onResume()是在该Activity将要和用户进行交互时被调用,此时Activity位于的活动栈顶部。

暂停状态(paused)

暂停状态一般指该Activity已失去了焦点但仍然是可见的状态(包括部分可见)。一个处于暂停状态的Activity只有在系统极度缺乏内存资源的情况下才会被系统强制结束。
运行状态到暂停状态所触发的函数及顺序为:onResume() -> onPuased()。
暂停状态恢复至运行状态所触发的函数及顺序为:onPuased() -> onResume()。
其中:
onPuased()是当一个Activity失去系统焦点后将会被调用,包括见面被部分遮挡,以及设备转入休眠状态等等。一般地在此期间对一些未保存的数据进行持久化并停止其他需要耗费CPU的操作,同时不可进行耗时操作,否则会阻塞系统UI线程。

停止状态(stopped)

停止状态一般指该Activity被另一个Activity完全覆盖的状态,这是它仍然保持所有的状态,但是由于该Activity变得不可见,所以系统经常会由于内存不足而将该Activity强行结束。
暂停状态到停止状态所触发的函数及顺序为:onPuased() -> onStop()。
停止状态恢复至运行状态所触发的函数及顺序为:onStop() -> onRestart() -> onStart() -> onResume()。
其中:
onStop()是当一个Activity变为不可见时将会被调用,此时可能是由于该Activity要被注销或新的Activity完全遮挡了该Activity。在此期间一般可以进行取消注册广播等操作,因为用户不可见。
onRestart()是当一个Activity从停止状态恢复至运行状态时将会被优先调用。

死亡状态

死亡态是指该Activity被系统销毁。当一个Activity处于暂停状态或停止状态时就随处可能进入死亡状态,因为系统可能因内存不足而强行结束该Activity。
停止状态到死亡状态分为两种情况:(1)由用户操作导致,则执行:onStop() -> onDestroy()。(2)由系统自动强制执行,则该Activity被强行结束。
其中:
onDestroy()是当一个Activity正在被系统finished期间被调用的。

  1. activity的生命周期分析

Activity启动 > onCreate() > onStart() > onResume() >
点击Home健回到主界面(Activity不可见) > onPause() > onStop() >
当我们再次回到原来Activity时 >onReStart() > onStart() >onResume...
退出当前Activity时 > onPause() > onStop() >onDestroy()


image.png
  1. android进程的优先级
    前台/可见/服务/后台/空(优先级从左往右最高到低的排序)

一个Android的应用进程中,都可能包含四大组件中的一个/种或者多个/种。
对于运行中的Service和ContentProvider来说,可能有若干个客户端进程正在对其使用。
应用进程是由ActivityManagerService发送请求让zygote创建的,并且ActivityManagerService中对于每一个运行中的进程都有一个ProcessRecord对象与之对应。
https://blog.csdn.net/omnispace/article/details/73320950

activity任务栈

image.png

1.1、关于任务栈的概念:

任务栈是用来提升体验而设计的:
(1) 程序打开时就创建了一个任务栈, 用于存储当前程序的activity,当前程序(包括被当前程序所调用的)所有的activity属于一个任务栈。
(2) 一个任务栈包含了一个activity的集合, 可以有序的选择哪一个activity和用户进行交互,只有在任务栈栈顶的activity才可以跟用户进行交互。
(3) 任务栈可以移动到后台,并且保留了每一个activity的状态. 并且有序的给用户列出它们的任务, 而且还不丢失它们状态信息。
(4) 退出应用程序时,当把所有的任务栈中所有的activity清除出栈时,任务栈会被销毁,程序退出。
1.2、关于任务栈的缺点:

(1) 每开启一次页面都会在任务栈中添加一个Activity,而只有任务栈中的Activity全部清除出栈时,任务栈被销毁,程序才会退出,这样就造成了用户体验差,需要点击多次返回才可以把程序退出了。
eg:


image.png

(2) 每开启一次页面都会在任务栈中添加一个Activity还会造成数据冗余重复数据太多,会导致内存溢出的问题(OOM)。

3 activity四种启动模式

1 Standard模式

Standard模式是Android的默认启动模式,你不在配置文件中做任何设置,那么这个Activity就是standard模式,这种模式下,Activity可以有多个实例,每次启动Activity,无论任务栈中是否已经有这个Activity的实例,系统都会创建一个新的Activity实例,以下是实验验证。

新建一个FirstActivity,用一个Button去启动它本身:

image.png

发现每次都会启动一个新的FristActivity, Log信息如下


image.png

什么时候用standard模式呢?standartd模式是activity的默认模式,大部分情况下,都应该使用这种模式,也就是在配置文件中什么都不用做,当确实有特殊需求时,再考虑其他模式。

  1. SingleTop模式
    SingleTop模式和standard模式非常相似,主要区别就是当一个singleTop模式的Activity已经位于任务栈的栈顶,再去启动它时,不会再创建新的实例,如果不位于栈顶,就会创建新的实例,现在把配置文件中FirstActivity的启动模式改为SingleTop,我们的应用只有一个Activity,FirstActivity自然处于任务栈的栈顶。
    当应用第一次启动后,我们再按Button去启动新的FirstActivity,发现Log信息中不再打印onCreate函数,说明不再创建新的FirstActivity实例。这里有一个新的问题,对于每次启动Activity,我们该如何分别处理。答案就是onNewIntent()函数,虽然系统不会调用onCreat(),但会调用onNewIntent,我们可以在这个函数做相应的处理。当一个Activity已经在栈顶,但依然有可能启动它,而你又不想产生新的Activity实例,此时就可以用singleTop模式。例如,一个搜索Activity,可以输入搜索内容,也可以产生搜索结果,此时就可以用singleTop模式,不会用户每次搜索都会产生一个实例。
image.png

3 SingleTask模式

SingleTask模式的Activity在同一个Task内只有一个实例,如果Activity已经位于栈顶,系统不会创建新的Activity实例,和singleTop模式一样。但Activity已经存在但不位于栈顶时,系统就会把该Activity移到栈顶,并把它上面的activity出栈。修改上面的程序,新建一个SecondActivity,将FirstActivity设置为singleTask启动模式,并让它启动SecondActivity,再让SecondActivity来启动FirstActivity。
image.png

Log信息如下


image.png

当SecondActivity启动FirstActivity时,并不会调用FirstActivity的onCreate函数,但会调用onNewIntent函数,同时会调用SecondActivity的onDestroy函数,SecondActivity实例被销毁。

singleTask模式和前面两种模式的最大区别就是singleTask模式是任务内单例的,所以我们是否设定Activity为singleTask模式,就是看我们activity是否需要单例,例如你的某个Activity

里面有一个列表,如果有多个实例,有可能导致用户看到的列表不一致,有的Activity需要经常启动,如果每次都创建实例,会导致占用资源过多,这些情况都可以使用singleTask模式,但启动singleTask模式的Activity会导致任务栈内它上面的Activity被销毁,有可能会影响用户体验,使用时要注意。

4 SingleInstance模式

singleInstance模式也是单例的,但和singleTask不同,singleTask只是任务栈内单例,系统里是可以有多个singleTask Activity实例的,而singleInstance Activity在整个系统里只有一个实例,启动一singleInstanceActivity时,系统会创建一个新的任务栈,并且这个任务栈只有他一个Activity。

SingleInstance模式并不常用,如果我们把一个Activity设置为singleInstance模式,你会发现它启动时会慢一些,切换效果不好,影响用户体验。它往往用于多个应用之间,例如一个电视launcher里的Activity,通过遥控器某个键在任何情况可以启动,这个Activity就可以设置为singleInstance模式,当在某应用中按键启动这个Activity,处理完后按返回键,就会回到之前启动它的应用,不影响用户体验。

以上分析了Activity的4种启动模式,将Activity设置为哪种启动模式并没有标准答案,有时候,你可能发现将某个Activity设置为一种启动模式或者另一种启动模式,并没有明显区别,而具体的评判标准就是看哪种模式更满足应用功能,更有利于用户体验。

4 activity的跳转协议

Scheme协议
Android中的Scheme是一种页面内跳转协议,通过自定义Scheme协议,可以跳转到app中的任何页面。

服务器可以定制化跳转app页面
app可以通过Scheme跳转到另一个app页面
可以通过h5页面跳转app原生页面

板块二 Fragment面试详解

1.Fragment为什么被称为第五大组件?

1..Fragment为什么被称为第五大组件?
Android 3.0 开始引入的API,Fragment英文翻译是碎片的意思。也可以把它当作Activity的子控件,Fragment的使用都是在Activity里面的,受Activity的生命周期影响。当然,它本身具有自己的生命周期。Android 3.0引入Fragment的初衷是为了适应平板电脑,但在实际开发中,开发者逐渐挖掘了Fragment的更多用途,如配合TabLayout+ViewPager实现分页管理等等。因此把Fragment成为四大组件外的第五大组件一点都不为过。


image.png

2.Fragmengt加载Activity的两种方式
(1) 添加Fragment到Activity的布局文件当中 -- 静态
(2) 动态在activity中添加fragment --动态

3.FragmentPagerAdapter 与 FragmentStatePagerAdapter区别(检验是否有多年开发经验)
FragmentPagerAdapter 适用于页面较少的情况,而FragmentStatePagerAdapter适用于页面较多的情况
FragmentStatePagerAdapter比FragmentPagerAdapter 更节省内存。
答:因为FragmentStatePagerAdapter在每次切换Viewpage会回收内存,适用于页面较多的情况。而FragmentPagerAdapter在getItem的时候并没有回收内存,只是把UI分离,对系统内存没多大影响。

2.Fragment的生命周期?

官网图:


image.png

下面是Fragment从启动到销毁的全过程


Screenshot_20190402_092040_com.baidu.netdisk_meitu_1.jpg

3.Fragment之间的通信

1.在Fragment中调用Activity中的方法 : getActivity
2.在Activity中调用Fragment中的方法 : 接口回调
3.在Fragment中调用Fragment中的方法 : findFragmentById
4.Fragment的replace、add、remove、方法
https://blog.csdn.net/u014699958/article/details/52996143

4.Fragment管理器:FragmentManager?

FragmentManager和FragmentTransaction总结
1.其中关于Manager,用的比较多的API:

  • getSupportFragmentManager():在Activity中使用Fragment的管理器,对所有Fragment进行管理。
  • getFragmentManager():与 getSupportFragmentManager()功能是一样的,只是是在Fragment中使用
  • getChildFragmentManager():在Fragment嵌套使用中经常使用到,但这里需要注意一个点,看下图:


    image.png

    在fragment创建childFragment的时候,需要注意的是:使用getChildFragmentManager() 使用getFragmentManager()会导致内存泄漏,在嵌套的Fragment中,内部的fragment创建,需要使用getChildFragmentManager()

2.FragmentTransaction常用的api:
add():将一个Fragment实例对象添加到集合列表的尾部,当展示的时候会在activity的最上层
remove():将一个Fragment实例对象从存储的集合列表中移除,并且将其从UI界面中销毁
replace():将上一个Fragmnt的实例对象从存储的集合列表中移除,将当前的Fragment实例对象添加到存储的链表尾部,当展示的时候会在activity的最上层
hide():将一个fragment,从展示状态隐藏起来,实例对象不被销毁
show():将一个fragment实例对象,展示出来
addToBackStack():将fragment添加到回退栈中
add() 和 replace() 运用总结:
在项目的使用中,通常习惯使用add()加载,add方式视图不会重建,会被保存起来,而replace()每次都会remove掉前面的视图,而replace方式的回退,旧的视图每一次都会重建,在用户体验上不好。
add()和replace()的使用,不能够混合使用,在混合使用的情况下,会导致回退栈混乱,导致的原因是在回退过程中记录的角标存在问题
hide() 和 show() 运用总结:通常的使用情况是在主界面上,有多Tab键切换情况

你可能感兴趣的:(高级Android面试(一) :基础相关面试)