Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
209 lines (157 sloc) 13.5 KB

目录介绍

  • 01.Activity异常生命周期
  • 02.后台Activity被系统回收
  • 03.如何判断activity优先级
  • 04.App切换到后台分析
  • 05.桌面launcher启动App
  • 06.Activity传递参数数据
  • 07.Activity任务战Task

好消息

  • 博客笔记大汇总【16年3月到至今】,包括Java基础及深入知识点,Android技术博客,Python学习笔记等等,还包括平时开发中遇到的bug汇总,当然也在工作之余收集了大量的面试题,长期更新维护并且修正,持续完善……开源的文件是markdown格式的!同时也开源了生活博客,从12年起,积累共计N篇[近100万字,陆续搬到网上],转载请注明出处,谢谢!
  • 链接地址:https://github.com/yangchong211/YCBlogs
  • 如果觉得好,可以star一下,谢谢!当然也欢迎提出建议,万事起于忽微,量变引起质变!

01.Activity异常生命周期

  • 虽然前面也说了这个异常的生命周期,但是还是有些疑问?
  • 异常条件会调用什么方法
    • 当非人为终止Activity时,比如系统配置发生改变时导致Activity被杀死并重新创建、资源内存不足导致低优先级的Activity被杀死,会调用 onSavaInstanceState() 来保存状态。该方法调用在onStop之前,但和onPause没有时序关系。
    • 有人会问,onSaveInstanceState()与onPause()的区别,onSaveInstanceState()适用于对临时性状态的保存,而onPause()适用于对数据的持久化保存。
    • 当异常崩溃后App又重启了,这个时候会走onRestoreInstanceState()方法,可以在该方法中取出onSaveInstanceState()保存的状态数据。
  • 什么时候会引起异常生命周期
    • 资源相关的系统配置发生改变或者资源不足:例如屏幕旋转,当前Activity会销毁,并且在onStop之前回调onSaveInstanceState保存数据,在重新创建Activity的时候在onStart之后回调onRestoreInstanceState。其中Bundle数据会传到onCreate(不一定有数据)和onRestoreInstanceState(一定有数据)。
    • 还有中情况是异常导致app崩溃,然后并没有完全杀死进程,重启回到activity页面,也会引起异常生命周期。

02.后台Activity被系统回收

  • 后台的Activity被系统回收怎么办?
    • Activity中提供了一个 onSaveInstanceState()回调方法,这个方法会保证一定在活动被回收之前调用,可以通过这个方法来解决活动被回收时临时数据得不到保存的问题。onSaveInstanceState()方法会携带一个Bundle类型的参数,Bundle提供了一系列的方法用于保存数据,比如可以使用putString()方法保存字符串,使用putInt()方法保存整型数据。每个保存方法需要传入两个参数,第一个参数是键,用于后面从 Bundle中取值,第二个参数是真正要保存的内容。
  • 说一下onSaveInstanceState()和onRestoreInstanceState()方法特点?
    • Activity的 onSaveInstanceState()和onRestoreInstanceState()并不是生命周期方法,它们不同于onCreate()、onPause()等生命周期方法,它们并不一定会被触发。
      //保存数据
      @Override
      protected void onSaveInstanceState(Bundle outBundle) {
      	super.onSaveInstanceState(outBundle);
       	outBundle.putBoolean("Change", mChange);
      }
      
      //取出数据
      @Override 
      protected void onRestoreInstanceState(Bundle savedInstanceState) {
      	super.onRestoreInstanceState(savedInstanceState);
      	mChange = savedInstanceState.getBoolean("Change");
      }
      
      //或者在onCreate方法取数据也可以
      //onCreate()方法其实也有一个Bundle类型的参数。这个参数在一般情况下都是null,
      //但是当活动被系统回收之前有通过 onSaveInstanceState()方法来保存数据的话,这个参就会带有之前所保存的全部数据
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          if (savedInstanceState != null) {
              String data = savedInstanceState.getString("data");
          }
      }
      
  • 什么时候会触发走这两个方法?
    • 当应用遇到意外情况(如:内存不足、用户直接按Home键)由系统销毁一个Activity,onSaveInstanceState() 会被调用。但是当用户主动去销毁一个Activity时,例如在应用中按返回键,onSaveInstanceState()就不会被调用。除非该activity是被用户主动销毁的,通常onSaveInstanceState()只适合用于保存一些临时性的状态,而onPause()适合用于数据的持久化保存。
  • onSaveInstanceState()被执行的场景有哪些?
    • 系统不知道你按下HOME后要运行多少其他的程序,自然也不知道activityA是否会被销毁,因此系统都会调用onSaveInstanceState(),让用户有机会保存某些非永久性的数据。以下几种情况的分析都遵循该原则当用户按下HOME键时
      • 长按HOME键,选择运行其他的程序时
      • 锁屏时
      • 从activity A中启动一个新的activity时
      • 屏幕方向切换时

03.如何判断activity优先级

  • 除了在栈顶的activity,其他的activity都有可能在内存不足的时候被系统回收,一个activity越处于栈底,被回收的可能性越大.如果有多个后台进程,在选择杀死的目标时,采用最近最少使用算法(LRU)。

04.App切换到后台分析

  • app切换到后台,当前activity会走onDestory方法吗?
    • 不会走onDestory方法,会先后走onPause和onStop方法。
  • 一般在onstop方法里做什么?
    • 比如。写轮播图的时候,会在onstop方法里写上暂停轮播图无限轮播,在onStart方法中会开启自动无限轮播。
    • 再比如,写视频播放器的时候,当app切换到后台,则需要停止视频播放,也是可以在onstop中处理的。关于视频播放器,可以看我这个开源项目:视频播放器
  • 什么情况会导致app会被杀死,这时候会走onDestory吗?
    • 系统资源不足,会导致app意外被杀死。应用只有在进程存活的情况下才会按照正常的生命周期进行执行,如果进程突然被kill掉,相当于System.exit(0); 进程被杀死,根本不会走(activity,fragment)生命周期。只有在进程不被kill掉,正常情况下才会执行ondestory()方法。
  • activity被回收如何恢复
    • 当系统内存不足时, activity会被回收,我们其实可以覆写onSaveInstanceState()方法。onSaveInstanceState()方法接受一个Bundle类型的参数, 开发者可以将状态数据存储到这个Bundle对象中,这样即使activity被系统摧毁,当用户重新启动这个activity而调用它的onCreate()方法时,上述的Bundle对象会作为实参传递给onCreate()方法,开发者可以从Bundle对象中取出保存的数据, 然后利用这些数据将activity恢复到被摧毁之前的状态。

05.桌面launcher启动App

  • App启动过程有哪些?
    • app启动的过程有两种情况,第一种是从桌面launcher上点击相应的应用图标,第二种是在activity中通过调用startActivity来启动一个新的activity。
  • 从桌面launcher上点击应用图标会干啥,调用startActivty()又会做什么?
    • 创建一个新的项目,默认的根activity都是MainActivity,而所有的activity都是保存在堆栈中的,启动一个新的activity就会放在上一个activity上面,而我们从桌面点击应用图标的时候,由于launcher本身也是一个应用,当我们点击图标的时候,系统就会调用startActivitySately(),一般情况下,我们所启动的activity的相关信息都会保存在intent中,比如action,category等等。
    • 我们在安装这个应用的时候,系统也会启动一个PackaManagerService的管理服务,这个管理服务会对AndroidManifest.xml文件进行解析,从而得到应用程序中的相关信息,比如service,activity,Broadcast等等,然后获得相关组件的信息。
    • 当我们点击应用图标的时候,就会调用startActivitySately()方法,而这个方法内部则是调用startActivty(),而startActivity()方法最终还是会调用startActivityForResult()这个方法。而在startActivityForResult()这个方法。因为startActivityForResult()方法是有返回结果的,所以系统就直接给一个-1,就表示不需要结果返回了。
    • 而startActivityForResult()这个方法实际是通过Instrumentation类中的execStartActivity()方法来启动activity,Instrumentation这个类主要作用就是监控程序和系统之间的交互。而在这个execStartActivity()方法中会获取ActivityManagerService的代理对象,通过这个代理对象进行启动activity。启动会就会调用一个checkStartActivityResult()方法,如果说没有在配置清单中配置有这个组件,就会在这个方法中抛出异常了。
    • 当然最后是调用的是Application.scheduleLaunchActivity()进行启动activity,而这个方法中通过获取得到一个ActivityClientRecord对象,而这个ActivityClientRecord通过handler来进行消息的发送,系统内部会将每一个activity组件使用ActivityClientRecord对象来进行描述,而ActivityClientRecord对象中保存有一个LoaderApk对象,通过这个对象调用handleLaunchActivity来启动activity组件,而页面的生命周期方法也就是在这个方法中进行调用。

06.Activity传递参数数据

  • 两个Activity之间怎么传递数据?
    • 基本数据类型可以通过Intent传递数据
    • 把数据封装至intent对象中
      Intent intent = new Intent(content, MeActivity.class);
      intent.putExtra("goods_id", goods_id);
      content.startActivity(intent);
      
    • 把数据封装至bundle对象中技术博客大总结
    • 把bundle对象封装至intent对象中
      Bundle bundle = new Bundle();
      bundle.putString("malename", "李志");
      intent.putExtras(bundle);
      startActivity(intent); 
      
  • intent和bundle有什么区别?
    • Intent传递数据和Bundle传递数据是一回事,Intent传递时内部还是调用了Bundle。
      public @NonNull Intent putExtra(String name, String value) {
          if (mExtras == null) {
              mExtras = new Bundle();
          }
          mExtras.putString(name, value);
          return this;
      }
      
  • 为什么有了intent还要设计bundle?
    • 两者比较
      • Bundle只是一个信息的载体,内部其实就是维护了一个Map<String,Object>。
      • Intent负责Activity之间的交互,内部是持有一个Bundle的。
    • bundle使用场景
      • Fragment之间传递数据;比如,某个Fragment中点击按钮弹出一个DialogFragment。最便捷的方式就是通过Fragment.setArguments(args)传递参数。
      public static void showFragmentDialog(String title, String content, boolean is_open, AppCompatActivity activity) {
          ServiceDialogFragment mainDialogFragment = new ServiceDialogFragment();
          Bundle bundle = new Bundle();
          bundle.putString("title", title);
          bundle.putString("content", content);
          bundle.putBoolean("is_open",is_open);
          mainDialogFragment.setArguments(bundle);
          mainDialogFragment.show(activity.getSupportFragmentManager());
      }
      
      @Override
      public void onCreate(Bundle savedInstanceState) {
          setLocal(Local.CENTER);
          super.onCreate(savedInstanceState);
          Bundle bundle = getArguments();
          if (bundle != null) {
              title = bundle.getString("title");
              content = bundle.getString("content");
              is_open = bundle.getBoolean("is_open");
          }
      }
      

07.Activity任务战Task

  • 同一程序不同的Activity是否可以放在不同的Task任务栈中?
    • 可以的。比如:启动模式里有个Singleinstance,可以运行在另外的单独的任务栈里面。用这个模式启动的activity,在内存中只有一份,这样就不会重复的开启。
    • 也可以在激活一个新的activity时候,给intent设置flag,Intent的flag添加FLAG_ACTIVITY_NEW_TASK,这个被激活的activity就会在新的task栈里面

其他介绍

01.关于博客汇总链接

02.关于我的博客

You can’t perform that action at this time.