01.Android之基础组件问题

目录介绍

  • 1.0.0.1 说下Activity的生命周期?屏幕旋转时生命周期?异常条件会调用什么方法?
  • 1.0.0.2 后台的Activity被系统回收怎么办?说一下onSaveInstanceState()和onRestoreInstanceState()方法特色?
  • 1.0.0.3 如何避免配置改变时Activity重建?优先级低的Activity在内存不足被回收后怎样作能够恢复到销毁前状态?
  • 1.0.0.4 app切换到后台,当前activity会走onDestory方法吗?通常在onstop方法里作什么?什么状况会致使app会被杀死?
  • 1.0.0.5 Activity的启动过程是有几种方式?从桌面launcher上点击应用图标会干啥,调用startActivty()又会作什么?
  • 1.0.0.6 说下Activity的四种启动模式?singleTop和singleTask的区别以及应用场景?任务栈的做用是什么?
  • 1.0.0.7 两个Activity之间怎么传递数据?intent和bundle有什么区别?为何有了intent还要设计bundle?
  • 1.0.0.8 知道哪些Activity启动模式的标记位?flag是干什么用的,何时用到?
  • 1.0.1.0 同一程序不一样的Activity是否能够放在不一样的Task任务栈中?
  • 1.0.1.1 介绍一下Service,启动Service有几种方式,生命周期是怎样的?说一下onStartCommand()的做用?service如何杀不死?
  • 1.0.1.2 一个Activty先start一个Service后,再bind时会回调什么方法?此时如何作才能回调Service的destory()方法?
  • 1.0.1.3 bindService是一个异步的过程吗?绑定service大概须要经历那些过程?
  • 1.0.1.4 是否能在Service进行耗时操做?若是非要能够怎么作,如何避免service线程卡顿?service里面能够弹土司吗?
  • 1.0.1.5 Activity如何与Service通讯?Service的生命周期与启动方法有什么区别?
  • 1.0.2.0 是否了解ActivityManagerService,它发挥什么做用,说一下AMS启动流程?
  • 1.0.2.1 Android中哪些事件须要用到广播?广播的生命周期是怎样的?
  • 1.0.2.3 广播有几种形式?他们分别有什么特色,如何使用广播?广播是怎么实现不一样进程之间通讯的?
  • 1.0.2.8 Fragment与Activity之间是如何传值的?Fragment与Fragment之间是如何传值的?
  • 1.0.2.9 Activity建立Fragment的方式是什么?FragmentPageAdapter和FragmentPageStateAdapter的区别?
  • 1.0.3.0 fragment 特色?说一下Fragment的生命周期?如何解决getActivity为null的异常问题?
  • 1.0.3.1 在fragment中为何有时getActivity()会为null?Fragment试图为何有的时候会重叠,怎么产生的,又如何解决?
  • 1.0.3.2 为何fragment传递数据不用构造方法传递?FragmentManager , add 和 replace 有什么区别?
  • 1.0.3.9 Activitiy启动流程中performLaunchActivity的做用?
  • 1.0.4.0 Intent是什么?Intent能够传递哪些数据?传递对象的时候为何要实例化?
  • 1.0.4.1 mipmap系列中xxxhdpi、xxhdpi、xhdpi、hdpi、mdpi和ldpi存在怎样的关系?
  • 1.0.4.2 res目录和assets目录的区别?R文件是如何生成的,主要有什么做用?
  • 1.0.4.3 Context是什么?Context有哪些类型,分别做用是什么?Context下有哪些子类?哪些场景只能用activity上下文?
  • 1.0.4.4 ActivityThread的main()的流程大概是怎么样的?
  • 1.0.5.0 序列化的方式有哪些?效率对比有何优点?如何作性能上分析的?
  • 1.0.5.9 界面的刷新为何需16.6ms?画面的显示须要哪些步骤?界面保持不变时还会16.6ms刷新一次屏幕吗?
  • 1.0.6.0 Android中日志级别有哪几种?开发中须要注意什么问题,打印日志源码分析原理是什么?

好消息

  • 博客笔记大汇总【15年10月到至今】,包括Java基础及深刻知识点,Android技术博客,Python学习笔记等等,还包括平时开发中遇到的bug汇总,固然也在工做之余收集了大量的面试题,长期更新维护而且修正,持续完善……开源的文件是markdown格式的!同时也开源了生活博客,从12年起,积累共计500篇[近100万字],将会陆续发表到网上,转载请注明出处,谢谢!
  • 连接地址:https://github.com/yangchong211/YCBlogs
  • 若是以为好,能够star一下,谢谢!固然也欢迎提出建议,万事起于忽微,量变引发质变!全部的笔记将会更新到GitHub上,同时保持更新,欢迎同行提出或者push不一样的见解或者笔记!

1.0.0.1 说下Activity的生命周期?屏幕旋转时生命周期?异常条件会调用什么方法?

  • 在Activity的生命周期涉及到七大方法,分别是:
    • onCreate()表示Activity 正在建立,常作初始化工做,如setContentView界面资源、初始化数据
    • onStart()表示Activity 正在启动,这时Activity 可见但不在前台,没法和用户交互
    • onResume()表示Activity 得到焦点,此时Activity 可见且在前台并开始活动
    • onPause()表示Activity 正在中止,可作 数据存储、中止动画等操做
    • onStop()表示activity 即将中止,可作稍微重量级回收工做,如取消网络链接、注销广播接收器等
    • onDestroy()表示Activity 即将销毁,常作回收工做、资源释放
    • onRestart()表示当Activity由后台切换到前台,由不可见到可见时会调用,表示Activity 从新启动
  • 屏幕旋转时生命周期
    • 屏幕旋转时候,若是不作任何处理,activity会通过销毁到重建的过程。通常这种效果都不是想要的。好比视频播放器就常常会涉及屏幕旋转场景。技术博客大总结
    • 第一种状况:当前的Activity不销毁【设置Activity的android:configChanges="orientation|keyboardHidden|screenSize"时,切屏不会从新调用各个生命周期,只会执行onConfigurationChanged方法】
      <activity
          android:name=".activity.VideoDetailActivity"
          android:configChanges="orientation|keyboardHidden|screenSize"
          android:screenOrientation="portrait"/>
      • 执行该方法
      //重写旋转时方法,不销毁activity
      @Override
      public void onConfigurationChanged(Configuration newConfig) {
      	super.onConfigurationChanged(newConfig);
      }
    • 第二种状况:销毁当前的Activity后重建,这种也尽可能避免。【不设置Activity的android:configChanges时,切屏会从新调用各个生命周期,默认首先销毁当前activity,而后从新加载】
  • 异常条件会调用什么方法
    • 当非人为终止Activity时,好比系统配置发生改变时致使Activity被杀死并从新建立、资源内存不足致使低优先级的Activity被杀死,会调用 onSavaInstanceState() 来保存状态。该方法调用在onStop以前,但和onPause没有时序关系。
    • 有人会问,onSaveInstanceState()与onPause()的区别,onSaveInstanceState()适用于对临时性状态的保存,而onPause()适用于对数据的持久化保存。
    • 当异常崩溃后App又重启了,这个时候会走onRestoreInstanceState()方法,能够在该方法中取出onSaveInstanceState()保存的状态数据。
  • 何时会引发异常生命周期
    • 资源相关的系统配置发生改变或者资源不足:例如屏幕旋转,当前Activity会销毁,而且在onStop以前回调onSaveInstanceState保存数据,在从新建立Activity的时候在onStart以后回调onRestoreInstanceState。其中Bundle数据会传到onCreate(不必定有数据)和onRestoreInstanceState(必定有数据)。技术博客大总结
    • 防止屏幕旋转的时候重建,在清单文件中添加配置:android:configChanges="orientation"

1.0.0.2 后台的Activity被系统回收怎么办?说一下onSaveInstanceState()和onRestoreInstanceState()方法特色?

  • 后台的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时
      • 屏幕方向切换时

1.0.0.3 如何避免配置改变时Activity重建?优先级低的Activity在内存不足被回收后怎样作能够恢复到销毁前状态?

  • 如何避免配置改变时Activity重建
    • 为了不因为配置改变致使Activity重建,可在AndroidManifest.xml中对应的Activity中设置android:configChanges="orientation|screenSize"。此时再次旋转屏幕时,该Activity不会被系统杀死和重建,只会调用onConfigurationChanged。所以,当配置程序须要响应配置改变,指定configChanges属性,重写onConfigurationChanged方法便可。
    • 使用场景,好比视频播放器横竖屏切换播放视频,就须要设置这种属性。具体能够看我封装的视频播放器库,地址:https://github.com/yangchong211/YCVideoPlayer
  • 优先级低的Activity在内存不足被回收后怎样作能够恢复到销毁前状态
    • 优先级低的Activity在内存不足被回收后从新打开会引起Activity重建。Activity被从新建立时会调用onRestoreInstanceState(该方法在onStart以后),并将onSavaInstanceState保存的Bundle对象做为参数传到onRestoreInstanceState与onCreate方法。所以可经过onRestoreInstanceState(Bundle savedInstanceState)和onCreate((Bundle savedInstanceState)来判断Activity是否被重建,并取出数据进行恢复。但须要注意的是,在onCreate取出数据时必定要先判断savedInstanceState是否为空。
  • 如何判断activity的优先级?技术博客大总结
    • 除了在栈顶的activity,其余的activity都有可能在内存不足的时候被系统回收,一个activity越处于栈底,被回收的可能性越大.若是有多个后台进程,在选择杀死的目标时,采用最近最少使用算法(LRU)。

1.0.0.4 app切换到后台,当前activity会走onDestory方法吗?通常在onstop方法里作什么?什么状况会致使app会被杀死,这时候会走onDestory吗?

  • 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恢复到被摧毁以前的状态。

1.0.0.5 Activity的启动过程是有几种方式?从桌面launcher上点击应用图标会干啥,调用startActivty()又会作什么?

  • Activity的启动过程是怎样的,有几种方式?
    • 注意是启动过程,不是生命周期。技术博客大总结
    • 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组件,而页面的生命周期方法也就是在这个方法中进行调用。

1.0.0.6 说下Activity的四种启动模式?singleTop和singleTask的区别以及应用场景?任务栈的做用是什么?

  • Activity的四种启动模式
    • standard标准模式:每次启动一个Activity就会建立一个新的实例
    • singleTop栈顶复用模式:若是新Activity已经位于任务栈的栈顶,就不会从新建立,并回调 onNewIntent(intent) 方法
    • singleTask栈内复用模式:只要该Activity在一个任务栈中存在,都不会从新建立,并回调 onNewIntent(intent) 方法。若是不存在,系统会先寻找是否存在须要的栈,若是不存在该栈,就建立一个任务栈,并把该Activity放进去;若是存在,就会建立到已经存在的栈中
    • singleInstance单实例模式:具备此模式的Activity只能单独位于一个任务栈中,且此任务栈中只有惟一一个实例
  • singleTop和singleTask的区别以及应用场景
    • singleTop:同个Activity实例在栈中能够有多个,便可能重复建立;该模式的Activity会默认进入启动它所属的任务栈,即不会引发任务栈的变动;为防止快速点击时屡次startActivity,能够将目标Activity设置为singleTop
    • singleTask:同个Activity实例在栈中只有一个,即不存在重复建立;可经过android:taskAffinity设定该Activity须要的任务栈,便可能会引发任务栈的变动;经常使用于主页和登录页
  • singleTop或singleTask的Activity在如下状况会回调onNewIntent()
    • singleTop:若是新Activity已经位于任务栈的栈顶,就不会从新建立,并回调 onNewIntent(intent) 方法
    • singleTask:只要该Activity在一个任务栈中存在,都不会从新建立,并回调 onNewIntent(intent) 方法
  • 任务栈的做用是什么?技术博客大总结
    • 它是存放 Activity 的引用的,Activity不一样的启动模式,对应不一样的任务栈的存放;可经过 getTaskId()来获取任务栈的 ID,若是前面的任务栈已经清空,新开的任务栈ID+1,是自动增加的;首先来看下Task的定义,Google是这样定义Task的:Task其实是一个Activity栈,一般用户感觉的一个Application就是一个Task。从这个定义来看,Task跟Service或者其余Components是没有任何联系的,它只是针对Activity而言的。

1.0.0.7 两个Activity之间怎么传递数据?intent和bundle有什么区别?为何有了intent还要设计bundle?

  • 两个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");
          }
      }

1.0.0.8 知道哪些Activity启动模式的标记位?flag是干什么用的,何时用到?

  • 常见的标记为:
    • FLAG_ACTIVITY_SINGLE_TOP:对应singleTop启动模式
    • FLAG_ACTIVITY_NEW_TASK :对应singleTask模式

1.0.1.0 同一程序不一样的Activity是否能够放在不一样的Task任务栈中?

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

1.0.1.1 介绍一下Service,启动Service有几种方式,生命周期是怎样的?说一下onStartCommand()的做用?service如何杀不死?

  • Service分为两种
    • 本地服务,属于同一个应用程序,经过startService来启动或者经过bindService来绑定而且获取代理对象。若是只是想开个服务在后台运行的话,直接startService便可,若是须要相互之间进行传值或者操做的话,就应该经过bindService。
    • 远程服务(不一样应用程序之间),经过bindService来绑定而且获取代理对象。
  • 对应的生命周期以下:
    • context.startService() ->onCreate()- >onStartCommand()->Service running--调用context.stopService() ->onDestroy()
    • context.bindService()->onCreate()->onBind()->Service running--调用>onUnbind() -> onDestroy()
  • 注意
    • Service默认是运行在main线程的,所以Service中若是须要执行耗时操做(大文件的操做,数据库的拷贝,网络请求,文件下载等)的话应该在子线程中完成。
  • Service生命周期解释技术博客大总结
    • onCreate():服务第一次被建立时调用
    • onStartComand():服务启动时调用
    • onBind():服务被绑定时调用
    • onUnBind():服务被解绑时调用
    • onDestroy():服务中止时调用
  • 说一下onStartCommand()的做用?
  • service如何杀不死?
    • 1.onStartCommand方法,返回START_STICKY(粘性)当service因内存不足被kill,当内存又有的时候,service又被从新建立
    • 2.设置优先级,在服务里的ondestory里发送广播 在广播里再次开启这个服务,双进程守护

1.0.1.2 一个Activty先start一个Service后,再bind时会回调什么方法?此时如何作才能回调Service的destory()方法?

  • 关于service中onDestroy()何时会被执行?
    • 当调用了startService()方法后,又去调用stopService()方法,这时服务中的onDestroy()方法就会执行,表示服务已经销毁了。
    • 相似地,当调用了 bindService()方法后,又去调用unbindService()方法,onDestroy()方法也会执行,这两种状况都很好理解。
  • 一个Activty先start一个Service后,再bind时会回调什么方法?

  • 先start后bind操做service,此时如何作才能回调Service的destory()方法?
    • 彻底有可能对一个服务既调用了startService()方法,又调用了bindService()方法的,这种状况下该如何才能让服务销毁掉呢?根据Android系统的机制,一个服务只要被启动或者被绑定了以后,就会一直处于运行状态,必需要让以上两种条件同时不知足,服务才能被销毁。
    • 这种状况下要同时调用stopService()和unbindService()方法,onDestroy()方法才会执行这样就把服务的生命周期完整地走了一遍。技术博客大总结

1.0.1.3 bindService是一个异步的过程吗?绑定service大概须要经历那些过程?

1.0.1.4 是否能在Service进行耗时操做?若是非要能够怎么作,如何避免service线程卡顿?service里面能够弹土司吗?

  • 是否能在Service进行耗时操做?
    • 默认状况,若是没有显示的指定service所运行的进程,Service和Activity是运行在当前app所在进程的mainThread(UI主线程)里面。
    • service里面不能执行耗时的操做(网络请求,拷贝数据库,大文件),在Service里执行耗时操做,有可能出现主线程被阻塞(ANR)的状况。
  • 若是非要能够怎么作,如何避免service线程卡顿?
    • 须要在子线程中执行 new Thread(){}.start();
  • service里面能够弹土司吗?
    • 能够,可是有条件。通常不多这样作……技术博客大总结
    • 条件是,service里面弹toast须要添加到主线程里执行。
      @Override  
      public void onCreate(){  
          handler = new Handler(Looper.getMainLooper());                          
          System.out.println("service started");  
          handler.post(new Runnable() {    
              @Override    
              public void run() {    
                  Toast.makeText(getApplicationContext(), "Test",Toast.LENGTH_SHORT).show();
              }
          });
      }

1.0.1.5 Activity如何与Service通讯?Service的生命周期与启动方法有什么区别?

  • Activity如何与Service通讯?
    • 方法一:
      • 添加一个继承Binder的内部类,并添加相应的逻辑方法。重写Service的onBind方法,返回咱们刚刚定义的那个内部类实例。Activity中建立一个ServiceConnection的匿名内部类,而且重写里面的onServiceConnected方法和onServiceDisconnected方法,这两个方法分别会在活动与服务成功绑定以及解除绑定的时候调用,在onServiceConnected方法中,咱们能够获得一个刚才那个service的binder对象,经过对这个binder对象进行向下转型,获得咱们那个自定义的Binder实例,有了这个实例,作能够调用这个实例里面的具体方法进行须要的操做了
    • 方法二
      • 经过BroadCast(广播)的形式,当咱们的进度发生变化的时候咱们发送一条广播,而后在Activity的注册广播接收器,接收到广播以后更新视图

1.0.2.0 是否了解ActivityManagerService,它发挥什么做用,说一下AMS启动流程?

  • ActivityManagerService是Android中最核心的服务,主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工做,其职责与操做系统中的进程管理和调度模块相似。
  • https://blog.csdn.net/dutedehuai/article/details/53495185

1.0.2.1 Android中哪些事件须要用到广播?广播的生命周期是怎样的?

  • Android中哪些事件须要用到广播?
    • Android中:系统在运行过程当中,会产生会多事件,那么某些事件产生时,好比:电量改变、收发短信、拨打电话、屏幕解锁、开机,系统会发送广播,只要应用程序接收到这条广播,就知道系统发生了相应的事件,从而执行相应的代码。使用广播接收者,就能够收听广播
  • 广播的生命周期是怎样的?
    • a.广播接收者的生命周期很是短暂的,在接收到广播的时候建立,onReceive()方法结束以后销毁;
    • b.广播接收者中不要作一些耗时的工做,不然会弹出 Application No Response错误对话框;
    • c.最好也不要在广播接收者中建立子线程作耗时的工做,由于广播接收者被销毁后进程就成为了空进程,很容易被系统杀掉;
    • d.耗时的较长的工做最好放在服务中完成;

1.0.2.3 广播有几种形式?他们分别有什么特色,如何使用广播?广播是怎么实现不一样进程之间通讯的?

  • 广播有几种形式
    • 普通广播:一种彻底异步执行的广播,在广播发出以后,全部的广播接收器几乎都会在同一时刻接收到这条广播消息,所以它们接收的前后是随机的。
    • 有序广播:一种同步执行的广播,在广播发出以后,同一时刻只会有一个广播接收器可以收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递,因此此时的广播接收器是有前后顺序的,且优先级(priority)高的广播接收器会先收到广播消息。有序广播能够被接收器截断使得后面的接收器没法收到它。
    • 本地广播:发出的广播只可以在应用程序的内部进行传递,而且广播接收器也只能接收本应用程序发出的广播。
    • 粘性广播:这种广播会一直滞留,当有匹配该广播的接收器被注册后,该接收器就会收到此条广播。
  • 广播的两种注册形式技术博客大总结
    • 广播的注册有两种方法:一种在活动里经过代码动态注册,另外一种在配置文件里静态注册。两种方式的相同点是都完成了对接收器以及它能接收的广播值这两个值的定义;不一样点是动态注册的接收器必需要在程序启动以后才能接收到广播,而静态注册的接收器即使程序未启动也能接收到广播,好比想接收到手机开机完成后系统发出的广播就只能用静态注册了。
  • 动态注册
    • 须要使用广播接收者时,执行注册的代码,不须要时,执行解除注册的代码。安卓中有一些广播接收者,必须使用代码注册,清单文件注册是无效的。
      public class MainActivity extends Activity {
          private IntentFilter intentFilter;
          private NetworkChangeReceiver networkChangeReceiver;
          @Override
          protected void onCreate(Bundle savedInstanceState) {
                 super.onCreate(savedInstanceState);
                 setContentView(R.layout.activity_main);
                 intentFilter = new IntentFilter();
                 intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
                 networkChangeReceiver = new NetworkChangeReceiver();
                 registerReceiver(networkChangeReceiver, intentFilter);
          }
          @Override
          protected void onDestroy() {
                 super.onDestroy();
                 unregisterReceiver(networkChangeReceiver);
          }
          class NetworkChangeReceiver extends BroadcastReceiver {
                  @Override
                  public void onReceive(Context context, Intent intent) {
                       Toast.makeText(context, "network changes",Toast.LENGTH_SHORT).show();
                  }
          }
      }
  • 静态注册
    • 可使用清单文件注册。广播一旦发出,系统就会去全部清单文件中寻找,哪一个广播接收者的action和广播的action是匹配的,若是找到了,就把该广播接收者的进程启动起来。

1.0.2.8 Fragment与Activity之间是如何传值的?Fragment与Fragment之间是如何传值的?

  • Fragment与Activity之间是如何传值的?
    • 1.Activity向Fragment传值:
      • 步骤:
      • 要传的值,放到bundle对象里;
      • 在Activity中建立该Fragment的对象fragment,经过调用
      • fragment.setArguments()传递到fragment中;
      • 在该Fragment中经过调用getArguments()获得bundle对象,就能获得里面的值。
    • 2.Fragment向Activity传值:
      • 第一种:
        • 在Activity中调用getFragmentManager()获得fragmentManager,,调用findFragmentByTag(tag)或者经过findFragmentById(id)
        • FragmentManager fragmentManager = getFragmentManager();
        • Fragment fragment = fragmentManager.findFragmentByTag(tag);
      • 第二种:
        • 经过回调的方式,定义一个接口(能够在Fragment类中定义),接口中有一个空的方法,在fragment中须要的时候调用接口的方法,值能够做为参数放在这个方法中,而后让Activity实现这个接口,必然会重写这个方法,这样值就传到了Activity中
  • Fragment与Fragment之间是如何传值的?
    • 第一种:
      • 经过findFragmentByTag获得另外一个的Fragment的对象,这样就能够调用另外一个的方法了。
    • 第二种:
    • 第三种:
      • 经过setArguments,getArguments的方式。

1.0.2.9 Activity建立Fragment的方式是什么?FragmentPageAdapter和FragmentPageStateAdapter的区别?

  • Activity建立Fragment的方式是什么?
    • 静态建立具体步骤
      • 首先咱们一样须要注册一个xml文件,而后建立与之对应的java文件,经过onCreatView()的返回方法进行关联,最后咱们须要在Activity中进行配置相关参数即在Activity的xml文件中放上fragment的位置。
    • 动态建立具体步骤
      • (1)建立待添加的碎片实例
      • (2)获取FragmentManager,在活动中能够直接经过调用 getSupportFragmentManager()方法获得。
      • (3)开启一个事务,经过调用beginTransaction()方法开启。
      • (4)向容器内添加或替换碎片,通常使用repalce()方法实现,须要传入容器的id和待添加的碎片实例。
      • (5)提交事务,调用commit()方法来完成。
  • FragmentPageAdapter和FragmentPageStateAdapter的区别?
    • FragmnetPageAdapter在每次切换页面时,只是将Fragment进行分离,适合页面较少的Fragment使用以保存一些内存,对系统内存不会多大影响
    • FragmentPageStateAdapter在每次切换页面的时候,是将Fragment进行回收,适合页面较多的Fragment使用,这样就不会消耗更多的内存

1.0.3.0 fragment 特色?说一下Fragment的生命周期?如何解决getActivity为null的异常问题?

  • fragment 特色
    • Fragment能够做为Activity界面的一部分组成出现;
    • 能够在一个Activity中同时出现多个Fragment,而且一个Fragment也能够在多个Activity中使用;
    • 在Activity运行过程当中,能够添加、移除或者替换Fragment;
    • Fragment能够响应本身的输入事件,而且有本身的生命周期,它们的生命周期会受宿主Activity的生命周期影响。
  • Fragment从建立到销毁整个生命周期中涉及到的方法依次为:
    • onAttach()->onCreate()->onCreateView()->onActivityCreated()->onStart()->onResume()->onPause()->onStop()->onDestroyView()->onDestroy()->onDetach(),其中和Activity有很多名称相同做用类似的方法,而不一样的方法有:
      • onAttach():当Fragment和Activity创建关联时调用
      • onCreateView():当Fragment建立视图时调用
      • onActivityCreated():当与Fragment相关联的Activity完成onCreate()以后调用
      • onDestroyView():在Fragment中的布局被移除时调用
      • onDetach():当Fragment和Activity解除关联时调用
  • 如何解决getActivity为null的异常问题技术博客大总结
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        activity = (PhoneNumActivity) context;
    }
    
    @Override
    public void onDetach() {
        super.onDetach();
        activity = null;
    }

1.0.3.1 在fragment中为何有时getActivity()会为null?Fragment试图为何有的时候会重叠,怎么产生的,又如何解决?

  • getActivity()空指针:
    • 这种状况通常发生在在异步任务里调用getActivity(),而Fragment已经onDetach(),此时就会有空指针,解决方案是在Fragment里使用一个全局变量mActivity,在onAttach()方法里赋值,这样可能会引发内存泄漏,可是异步任务没有中止的状况下自己就已经可能内存泄漏,相比直接crash,这种方式显得更稳当一些。
  • Fragment视图重叠:
    • 在类onCreate()的方法加载Fragment,而且没有判断saveInstanceState==null或if(findFragmentByTag(mFragmentTag) == null),致使重复加载了同一个Fragment致使重叠。(PS:replace状况下,若是没有加入回退栈,则不判断也不会形成重叠,但建议仍是统一判断下)
    @Override 
    protected void onCreate(@Nullable Bundle savedInstanceState) {
    // 在页面重启时,Fragment会被保存恢复,而此时再加载Fragment会重复加载,致使重叠 ;
        if(saveInstanceState == null){
        // 或者 if(findFragmentByTag(mFragmentTag) == null)
           // 正常状况下去 加载根Fragment 
        } 
    }

1.0.3.2 为何fragment传递数据不用构造方法传递?FragmentManager , add 和 replace 有什么区别?

  • 为何fragment传递数据不用构造方法传递?
    • activity给fragment传递数据通常不经过fragment的构造方法来传递,会经过setArguments来传递,由于当横竖屏会调用fragment的空参构造函数,数据丢失。
  • FragmentManager , add 和 replace 有什么区别?
    • 使用FragmentTransaction的时候,它提供了这样两个方法,一个add,一个replace,add和replace影响的只是界面,而控制回退的,是事务。
    • add 是把一个fragment添加到一个容器container里。replace是先remove掉相同id的全部fragment,而后在add当前的这个fragment。技术博客大总结
    • 在大部分状况下,这两个的表现基本相同。由于,通常,我们会使用一个FrameLayout来当容器,而每一个Fragment被add 或者 replace 到这个FrameLayout的时候,都是显示在最上层的。因此你看到的界面都是同样的。可是,使用add的状况下,这个FrameLayout其实有2层,多层确定要比一层的来得浪费,因此仍是推荐使用replace。固然有时候仍是须要使用add的。好比要实现轮播图的效果,每一个轮播图都是一个独立的Fragment,而他的容器FrameLayout须要add多个Fragment,这样他就能够根据提供的逻辑进行轮播了。而至于返回键的时候,这个跟事务有关,跟使用add仍是replace没有任何关系。
    • replace()方法会将被替换掉的那个Fragment完全地移除掉,所以最好的解决方案就是使用hide()和show()方法来隐藏和显示Fragment,这就不会让Fragment的生命周期重走一遍了。

1.0.3.9 Activitiy启动流程中performLaunchActivity的做用?Activity启动流程中handleResumeActivity的做用?

  • Activitiy启动流程中performLaunchActivity的做用?
    • 从ActivityClientRecord中获取到待启动的Activity的组件信息
    • 使用类加载器建立Activity对象
    • 经过LoadedApk的方法建立Applicayiton对象,该对象惟一,不会重复建立。
    • 会建立ContextImpl而且创建Context和Activity的联系,以及建立PhoneWindow,创建Window和Activity的联系。
    • 调用Activity的onCreate()
  • Activity启动流程中handleResumeActivity的做用?
    • 执行onStart()、onResume()—利用Instrucmentation
    • 获取Window
    • 建立DecorView、设置为不可见INVISIBLE、创建DecorView和Activity的联系。
    • 获取Activity的WindowManager
    • 调用WindowManager.addView(decorView, ...)将DecorView添加到WM中,完成显示的工做。
    • image
  • 什么时候将DecorView设置为VISIBLE?而且显示出来?技术博客大总结
    • 也是在handleResumeActivity中
    • 现将DecorView设置为不可见
    • wm.addView(): 将DecorView添加到Window总
    • 而后执行makeVisible让DecorView可见
    • image

1.0.4.0 Intent是什么?Intent能够传递哪些数据?传递对象的时候为何要实例化?

  • Intent是一种运行时绑定(run-time binding)机制,它能在程序运行过程当中链接两个不一样的组件。
    • 举例:好比,有一个Activity但愿打开网页浏览器查看某一网页的内容,那么这个Activity只须要发出 WEB_SEARCH_ACTION给Android
    • Android就会根据Intent的请求内容,查询各组件注册时声明的 IntentFilter,找到网页浏览器的Activity来浏览网页
  • Intent能够传递的数据基本数据类型的数据,数组,还有集合,还有序列化的对象
    • 序列化:表示将一个对象转换成可存储或可传输的状态
    • Android中序列化对象方式:技术博客大总结
      • 第一种:JAVA中的Serialize机制,译成串行化、序列化……,其做用是能将数据对象存入字节流当中,在须要时从新生成对象。主要应用是利用外部存储设 备保存对象状 态,以及经过网络传输对象等。
      • 第二种:在Android系统中,定位为针对内存受限的设备,所以对性能要求更高,另外系统中采用了新的IPC(进程间通讯)机制,必然要求使用性能更出色的对象传输方式。

1.0.1.2 Activity如与Service通讯?Service的生命周期与启动方法由什么区别?

能够经过bindService的方式,先在Activity里实现一个ServiceConnection接口,并将该接口传递给bindService()方法,在ServiceConnection接口的onServiceConnected()方法
里执行相关操做。

Service的生命周期与启动方法由什么区别?
    startService():开启Service,调用者退出后Service仍然存在。
    bindService():开启Service,调用者退出后Service也随即退出。

Service生命周期:
    只是用startService()启动服务:onCreate() -> onStartCommand() -> onDestory
    只是用bindService()绑定服务:onCreate() -> onBind() -> onUnBind() -> onDestory
    同时使用startService()启动服务与bindService()绑定服务:onCreate() -> onStartCommnad() -> onBind() -> onUnBind() -> onDestory

1.1.0.4 广播有哪些注册方式?有什么区别?广播发送和接收原理是什么[binder如何运做的]?

  • 广播有哪些注册方式?
    • 静态注册:常驻系统,不受组件生命周期影响,即使应用退出,广播仍是能够被接收,耗电、占内存。
    • 动态注册:很是驻,跟随组件的生命变化,组件结束,广播结束。在组件结束前,须要先移除广播,不然容易形成内存泄漏。
  • 广播发送和接收原理是什么[binder如何运做的]?
    • 继承BroadcastReceiver,重写onReceive()方法。
    • 经过Binder机制向ActivityManagerService注册广播。
    • 经过Binder机制向ActivityMangerService发送广播。
    • ActivityManagerService查找符合相应条件的广播(IntentFilter/Permission)的BroadcastReceiver,将广播发送到BroadcastReceiver所在的消息队列中。
    • BroadcastReceiver所在消息队列拿到此广播后,回调它的onReceive()方法。

1.0.4.1 mipmap系列中xxxhdpi、xxhdpi、xhdpi、hdpi、mdpi和ldpi存在怎样的关系?

  • 表示不一样密度的图片资源,像素从高到低依次排序为xxxhdpi>xxhdpi>xhdpi>hdpi>mdpi>ldpi,根据手机的dpi不一样加载不一样密度的图片

1.0.4.2 res目录和assets目录的区别?

  • assets:不会在 R文件中生成相应标记,存放到这里的资源在打包时会打包到程序安装包中。(经过 AssetManager 类访问这些文件)
  • res:会在 R 文件中生成 id标记,资源在打包时若是使用到则打包到安装包中,未用到不会打入安装包中。
  • res/anim:存放动画资源
  • res/raw:和 asset下文件同样,打包时直接打入程序安装包中(会映射到 R文件中)

1.0.4.3 Context是什么?Context有哪些类型,分别做用是什么?Context下有哪些子类?哪些场景只能用activity上下文?

  • Context是什么?
    • Context是一个抽象基类。在翻译为上下文,也能够理解为环境,是提供一些程序的运行环境基础信息。
  • Context有哪些类型,分别做用是什么?
    • Context下有两个子类,ContextWrapper是上下文功能的封装类,而ContextImpl则是上下文功能的实现类。
    • ContextWrapper又有三个直接的子类,ContextThemeWrapper、Service和Application。其中,ContextThemeWrapper是一个带主题的封装类,而它有一个直接子类就是Activity,因此Activity和Service以及Application的Context是不同的,只有Activity须要主题,Service不须要主题。
  • Context下有哪些子类,主要是干什么的?
    • Context一共有三种类型,分别是Application、Activity和Service。
    • 这三个类虽然分别各类承担着不一样的做用,但它们都属于Context的一种,而它们具体Context的功能则是由ContextImpl类去实现的,所以在绝大多数场景下,Activity、Service和Application这三种类型的Context都是能够通用的。
    • 不过有几种场景比较特殊,好比启动Activity,还有弹出Dialog。出于安全缘由的考虑,Android是不容许Activity或Dialog凭空出现的,一个Activity的启动必需要创建在另外一个Activity的基础之上,也就是以此造成的返回栈。而Dialog则必须在一个Activity上面弹出(除非是系统级别吐司),所以在这种场景下,咱们只能使用Activity类型的Context,不然将会出错。

1.0.4.4 ActivityThread的main()的流程大概是怎么样的?

  • ActivityThread的main()的流程大概是怎么样的?
    • image

1.0.5.0 序列化的方式有哪些?效率对比有何优点?如何作性能上分析的?

  • 序列化的方式有哪些
    • Parcelable
      • Parcelable是Android特有的一个实现序列化的接口,在Parcel内部包装了可序列化的数据,能够在Binder中自由传输。序列化的功能由writeToParcel方法来完成,最终经过Parcel的一系列write方法完成。反序列化功能由CREAOR来完成,其内部标明了如何建立序列化对象和数组,并经过Parcel的一系列read方法来完成反序列化的过程。
    • Serializable
      • Serializable是Java提供的一个序列化接口,是一个空接口,用于标示对象是否能够支持序列化,经过ObjectOutputStrean及ObjectInputStream实现序列化和反序列化的过程。注意能够为须要序列化的对象设置一个serialVersionUID,在反序列化的时候系统会检测文件中的serialVersionUID是否与当前类的值一致,若是不一致则说明类发生了修改,反序列化失败。所以对于可能会修改的类最好指定serialVersionUID的值。

1.0.5.9 界面的刷新为何需16.6ms?画面的显示须要哪些步骤?界面保持不变时还会16.6ms刷新一次屏幕吗?

  • 界面的刷新为何需16.6ms?
    • 系统每16.6ms会发出一个VSYNC信号,发出信号后,才会开始进行测量、布局和绘制。
    • 发出VSYNC信号时,还会将此时显示器的buffer缓冲区的数据取出,并显示在屏幕上。
  • 画面的显示须要哪些步骤?
    • CPU计算数据(View树遍历并执行三大流程:测量、布局和绘制),而后将数据交给GPU“
    • GPU渲染处理,而后将数据放到Buffer中。
    • 显示屏(display)从buffer中取出数据,并进行显示。
  • 界面保持不变时还会16.6ms刷新一次屏幕吗?技术博客大总结
    • 对于底层显示器,每间隔16.6ms接收到VSYNC信号时,就会用buffer中数据进行一次显示。因此必定会刷新。
  • 界面刷新的本质流程
    • 经过ViewRootImpl的scheduleTraversals()进行界面的三大流程。
    • 调用到scheduleTraversals()时不会当即执行,而是将该操做保存到待执行队列中。并给底层的刷新信号注册监听。
    • 当VSYNC信号到来时,会从待执行队列中取出对应的scheduleTraversals()操做,并将其加入到主线程的消息队列中。
    • 主线程从消息队列中取出并执行三大流程: onMeasure()-onLayout()-onDraw()

1.0.6.0 Android中日志级别有哪几种?开发中须要注意什么问题,打印日志源码分析原理是什么?

  • Android中日志级别有哪几种?
    • 1.Log.v 的输出颜色为黑色的,输出大于或等于VERBOSE日志级别的信息,也就是可见级别,通常是最低的信息提示
    • 2.Log.d的输出颜色是蓝色的,也就是调式级别,通常不会停止程序,通常是程序员为了调试而打印的log
    • 3.Log.i的输出为绿色,输出大于或等于INFO日志级别的信息,也就是信息界级别,不会停止程序,通常是系统中执行操做的信息提示
    • 4.Log.w的输出为橙色, 输出大于或等于WARN日志级别的信息,也就是警告级别,通常不会停止程序,可是可能会影响程序执行结果
    • 5.Log.e的输出为红色,仅输出ERROR日志级别的信息,也就是错误级别,通常会停止程序运行,是最严重的Log级别。
    • 解释:
      • verbose
      • debug调试
      • info信息
      • warn警告
      • error偏差
  • 经过查看源代码咱们发现Log类中全部的静态日志方法Log.v(),Log.d(),Log.i(),Log.w(),Log.e()等方法都是底层都是调用了println方法,而后在源码中查看,其实其内部调用的是println_native方法,也就是经过JNI调用底层的c++输出日志。

关于其余内容介绍

01.关于博客汇总连接

02.关于个人博客

相关文章
相关标签/搜索