求职与面试(一):Android必备

本文详细探讨了Android面试中的基础问题,包括Activity与View系列、Fragment、Service、Broadcast、ContentProvider等方面,深入讲解了Activity的生命周期、布局优化、数据存储方式、网络请求优化等关键知识点,同时涵盖了内存管理和跨进程通信。通过对这些问题的解析,帮助读者掌握Android开发的核心概念和最佳实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2019年的冬天有点冷,一份基础面试题送给还在奋斗在Android领域的同学.


Android基础问题

Activity&View系列

简述Android的布局分类?

早期Android官方提供以下五种布局:

  • LinearLayout
  • RelativeLayout
  • FrameLayout
  • GridLayout
  • TableLayout

以上传统的布局,以LinearLayout和RelativeLayout最为常用,但是或多或少有些缺陷,比如RelativeLayout需要两次measure它的子View才能之道确切的大小;而LinearLayout布局的子View在使用layout_weight属性后,同样也需要两次measure过程.

为此Android官方推出了两种新的布局:

  • ConstraintLayout: 约束布局,类似RelativeLayout,但更加灵活,再复杂的界面也可以只有2层
  • FlexboxLayout: 弹性布局,类似前端FlexBox,一种更高级的LinearLayout

如何分析布局问题?

判断布局是否有问题,可以借助Hierarchy Viewer工具,简称HV,该工作可以分析每个布局的measure,layout,draw三个过程的耗时.

需要注意的是在Root设备或者Dev版的ROM上可以直接使用,而在没有Root的手机需要在PC端添加环境变量ANDROID_HVPROTO=ddm

谈谈Activity的生命周期

image-20181111193213312

Activity实例是由系统自动创建,并在不同的状态期间回调相应的方法.一个最简单的完整的Activity生命周期会按照如下顺序回调:onCreate -> onStart -> onResume -> onPause -> onStop -> onDestroy.

  • 启动Activity:onCreate() -> onStart() -> onResume(),Activity进入运行状态
  • Activity退居后台: 当前Activity转到新的Activity界面或按Home键回到主屏:onPause() -> onStop()
  • Activity返回前台:onRestart() -> onStart() -> onResume(),再次回到运行状态

介绍不同场景下Activity生命周期的变化过程

假设A Activity位于栈顶,此时用户操作,从A Activity跳转到B Activity.那么对AB来说.具体会回调哪些生命周期中的方法呢?回调方法的具体回调顺序又是怎么样的呢?

  1. 当用户点击A中按钮来到B时,假设B全部遮挡住了A,将依次执行A:onPause -> B:onCreate -> B:onStart -> B:onResume -> A:onStop.
  2. 此时如果点击Back键,将依次执行B:onPause -> A:onRestart -> A:onStart -> A:onResume -> B:onStop -> B:onDestroy

至此,Activity栈中只有A.在Android中,有两个按键在影响Activity生命周期这块需要格外区分下,即Back键和Home键.

  • 此时如果按下Back键,系统返回到桌面,并依次执行A:onPause -> A:onStop -> A:onDestroy
  • 此时如果按下Home键(非长按),系统返回到桌面,并依次执行A:onPause -> A:onStop.由此可见Back键和Home键主要区别在于是否会执行onDestroy.

开启开发者选项中"不保留活动"对Activity生命周期有什么影响?

开启此设置项后,当A到B时,假设B全部遮挡住了A,将依次执行:

A:onPause -> B:onCreate -> B:onStart -> B:onResume -> A:onStop -> A:onDestroy

不难看出,A在系统原本的生命周期回调中增加了onDestroy,此即“用户离开后即销毁每个活动”的含义.需要注意的是,只要没有人为的调用A的finish()方法,虽然A执行了onDestroy,但Activity栈中依然保留有A,此时B处于栈顶.

那么在B中按Back键回到A时,将依次执行:

B:onPause -> A:onCreate -> A:onStart -> A:onResume -> B:onStop -> B:onDestroy

可以看出A从onCreate开始执行.

Activity的finish()onDestory()联系?

  • 对于finish()方法:当调用此方法的时候系统只是将最上面的Activity移出了栈,并没有及时的调用onDestory()方法,其占用的资源也没有被及时释放.因为移出了栈,所以当你点击手机上面的“back”按键的时候,也不会再找到这个Activity

  • 对于onDestory()方法:系统销毁了这个Activity的实例在内存中占据的空间.在Activity的生命周期中,onDestory()方法是他生命的最后一步,资源空间等就被回收了.当重新进入此Activity的时候,必须重新创建,执行onCreate()方法

简单来说就是:finish()方法用于结束一个Activity的生命周期,而onDestory()方法则是Activity的一个生命周期方法,其作用是在一个Activity对象被销毁之前,Android系统会调用该方法,用于释放此Activity之前所占用的资源.

如何判断Activity是否已经被销毁?简写代码

        if (activity == null || activity.isDestroyed() || activity.isFinishing()) {
   
   
            return;
        }

需要注意isFinishing()只有在主动调用finish()方法主动结束一个Activity时才会返回true.

Activity销毁但Task如果没有销毁掉,当Activity重启时这个AsyncTask该如何解决?

当一个屏幕发生旋转时,当前Activity会被销毁和重建.在当Activity重启时,AsyncTask持有该Activity将失效,因此onPostExecute()不会起作用.若AsynTask正在执行,此时会报 view not attached to window manager 异常.

通常对于生命周期问题,一般的解决思路是将其进行同步,对于AsyncTask而言可以在Activity的onDestory()方法中调用Asyntask.cancel()方法.

现在有两个应用A和B,先打开A应用,假设依次打开其A-Page1,A-Page2,A-Page3三个Activity,此时回到桌面,打开B应用,假设由于B应用非常大,促使系统杀死了A应用,此时回到桌面,点击A应用图标,请问出现什么情况?

对于由于系统原因导致进程被杀死的情况,在重新打开该应用的时候,系统会恢复进程被杀死之前栈顶的元素,此时我们看到的是A-Page3,按back键后A-Page2会被重建,继续按back键后A-Page1会被重建.

应用被杀死之前:

image-20181202144912953

后台被杀死的情况:

image-20181202145009010

应用恢复后的情况:

image-20181202145049663

继续点back键的情况:

image-20181202145144423

image-20181202145215779

内存不足时,系统会杀死后台的Activity,此时如何保存当前Activity的某些状态?如何恢复?

有A,B两个Activity,当从A进入B之后一段时间,可能系统会把A回收,这时候按back,执行的不是A的onRestart而是onCreate方法即A被重新创建一次,这A中的临时数据和状态可能就丢失了.在Activity中,提供了onSaveInstanceState()/onRestoreInstanceState()回调方法用于临时保存/恢复数据,其使用实例代码如下:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
   
   
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if( savedInstanceState != null ){
   
   
            savedInstanceState.getString("anAnt");
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
   
   
        // 将需要的数据保存到outState中
        super.onSaveInstanceState(outState);
    }

	@Override
	public void onRestoreInstanceState(Bundle savedInstanceState) {
   
   
        super.onRestoreInstanceState(savedInstanceState);
		// 从savedInstanceState中取出数据
    }

}

onSaveInstanceState()的工作原理是什么?

当某个Activity变得“容易”被系统销毁时,该Activity的onSaveInstanceState()就会被调用,除非该activity是被用户主动销毁的,例如当用户按BACK键的时候.

那Activity什么时候处在"容易"被销毁时呢?在以下几种情况中,Activity处在易被销毁的状态:

  1. 按下HOME键后,该Activity进入后台,由于系统不知道我们按下HOME后要可能要运行多少其他的程序,也就不知道该Activity是否会被销毁,此时系统会调用onSaveInstanceState()
  2. 长按HOME键,选择运行其他应用程序,原理同上
  3. 按下电源按键(关闭屏幕显示)
  4. 从Activity A中启动一个新的Activity时,由于系统可能会在某些时机回收掉A,因此系统会调用onSaveInstanceState()
  5. 屏幕方向切换时,会导致Activity实例重建,因此系统需要调用onSaveInstanceState()以便在重建后的Activity显示之前的Activity状态.

简单来说,只要系统未经你许可而销毁了你的Activity是,系统一定会调用onSaveInstanceState().对于该方法,需要注意一下几点:

  • 只有你为布局中的每个View设置了id,且实现了其onSaveInstanceState()时,系统才会对这个UI的任何改变自动存储及恢复.
  • 重写该方法时,最好需要显示调用super.onSaveInstanceState(),如果需要额外保存自己的UI数据,那么在进行额外操作.
  • 不要滥用onSaveInstanceState(),需要谨记其目的是为了保存当前界面的瞬时状态.

onRestoreInstanceState()的工作原理是什么?

onRestoreInstanceState()被调用的前提是,Activity A“确实”被系统销毁了,而不是处在可能被销毁的状态下.比如当正在显示Activity A的时候,按下HOME键回到主界面,紧接着又返回到Activity A,这种情况下Activity A一般不会因为内存的原因被系统销毁,因此Activity A的onRestoreInstanceState()方法不会被执行.

onRestoreInstanceState()onStart()后进行回调,此外onRestoreInstanceState()中的bundle参数也会传递到onCreate(Bundle savedInstanceState)方法中.

那在什么时候进行数据恢复呢?或者说恢复在这两个方法中进行恢复操作有什么不同?当在onCreate()中恢复数据时,需要对savedInstanceState进行判空操作,而在

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值