一、Activity

1、Activity生命周期

Activity生命周期
可以完整的写下来,注意不要遗漏了onReastart()方法。

2、Android任务栈

Android是基于组件开发的软件架构,虽然我们开发android程序,仍然使用一个apk工程一个Application的开发形式,但是对于Aplication的开发就用到了Activity、service等四大组件,其中的每一个组件,都是可以被跨应用复用的,这就是android的神奇之处。虽然组件可以跨应用被调用,但是一个组件所在的进程必须是在组件所在的Aplication进程中。由于android强化了组件概念,弱化了Aplication的概念,所以在android程序开发中,A应用的A组件想要使用拍照或录像的功能就可以不用去针对Camera类进行开发,直接调用系统自带的摄像头应用(称其B应用)中的组件(称其B组件)就可以了,但是这就引发了一个新问题,A组件运行在A应用中,B组件运行在B应用中,自然都不在同一个进程中,那么从B组件中返回的时候,如何实现正确返回到A组件呢?Task就是来负责实现这个功能的,它是从用户角度来理解应用而建立的一个抽象概念。因为用户所能看到的组件就是Activity,所以Task可以理解为实现一个功能而负责管理所有用到的Activity实例的栈。

3、Activity启动模式

理解启动模式,还需要看看这篇文章:Activity的启动模式

  • Standar:每次启动一个Activity,都会重新创建一个Activity的实例,然后把它放入任务栈中。他不考虑栈中是否已经存在这个Activity的实例,是非常消耗资源的。一般不用这种模式。

  • SingleTop:栈顶复用模式,如果要创建的Activity在任务栈顶存在,就不存在。应用场景:在通知栏点击收到的通知,然后需要启动一个Activity,这个Activity就可以用singleTop,否则每次点击都会新建一个Activity。当然实际的开发过程中,测试妹纸没准给你提过这样的bug:某个场景下连续快速点击,启动了两个Activity。如果这个时候待启动的Activity使用 singleTop模式也是可以避免这个Bug的。

  • SingleTask:栈内复用,如果整个任务栈中存在当前需要启动的Activity,就把该Activity置于栈顶,该Activity上面的所有Activity都清除销毁。 应用场景:大多数App的主页。对于大部分应用,当我们在主界面点击回退按钮的时候都是退出应用,那么当我们第一次进入主界面之后,主界面位于栈底,以后不管我们打开了多少个Activity,只要我们再次回到主界面,都应该使用将主界面Activity上所有的Activity移除的方式来让主界面Activity处于栈顶,而不是往栈顶新加一个主界面Activity的实例,通过这种方式能够保证退出应用时所有的Activity都能报销毁。

  • SingleInstance:这个Activity在整个系统中只有一个实例,且独享一个任务栈。应用场景:呼叫来电界面。这种模式的使用情况比较罕见,在Launcher中可能使用。或者你确定你需要使Activity只有一个实例。建议谨慎使用。

4、Activity的启动过程

面试不会问,可以作为了解。

ActivityThread的main()方法是程序的入口。

5、onSaveInstanceState()与onRestoreInstanceState()

1、onSaveInstanceState()

  • 用于保存Activity的状态,存储一些临时数据

  • Activity被覆盖或进入后台、用户改变屏幕方向、由于系统资源不足被kill,会被调用

  • 会在onStop之前被调用,和onPause的顺序不固定的

2、onRestoreInstanceState()

  • 用于恢复保存的临时数据,此方法的Bundle参数也会传递到onCreate方法中,你也可以在onCreate(Bundle savedInstanceState)方法中恢复数据

  • onRestoreInstanceState和onCreate的区别:当onRestoreInstanceState被调用时Bundle参数一定是有值的,不用做为null判断,onCreate的Bundle则可能会为null。官方文档建议在此方法中进行数据恢复。

  • 由于系统资源不足被kill之后又回到此Activity、用户改变屏幕方向重建Activity时,会被调用

  • 会在onStart之后被调用

Q1:如果一个Activity在用户可见时才处理某个广播,不可见时注销掉,那么应该在哪两个生命周期的回调方法去注册和注销BroadcastReceiver呢?

A:Activity 的可见生命周期发生在 onStart调用与 onStop调用之间。在这段时间,用户可以在屏幕上看到 Activity 并与其交互。我们可以在 onStart中注册一个 BroadcastReceiver以监控影响 UI 的变化,并在用户无法再看到您显示的内容时在 onStop中将其取消注册。

Q2:如果有一些数据在Activity跳转时(或者离开时)要保存到数据库,那么你认为是在onPause好还是在onStop执行这个操作好呢?

A:这题的要点和上一题是一样的,onPause较容易被触发,所以我们在做BroadcastReceiver注销时放在onStop要好些。onPause时Activity界面仍然是可见的,如弹出一个Dialog时。但在保存数据时,放在onPause去做可以保证数据存储的有效性,如果放在onStop去做,在某些情况下Activity走完onPause后有可能还没顺利走到onStop就被系统回收了。

Q3:简单说一下Activity A启动Activity B时,两个Activity生命周期的变化。

A:
1、Activity A 的 onPause方法执行。

2、Activity B 的 onCreate、onStart和 onResume方法依次执行。

3、然后,如果 Activity A 在屏幕上不再可见,则其 onStop方法执行。

Q4:如何判断Activity是否在运行?

从Activity A 启动一个线程去进行网络上传操作,在A中设立一个回调函数,当上传操作完成以后,在A的这个回调函数中会弹出一个对话框,用来显示回调信息。可是当上传的过程还在进行的时候,我按下back键,A的activity 被销毁了,可是那个上传的线程还在进行,当那个线程结束后,本来应该在A中弹出一个对话框,可是由于A已经不存在了,系统就会报错提示,“将对话框显示在不存在的页面上”,然后程序就挂掉了。

A:我看到过很多人用Handler来充当上面所提到的“回调函数”,即工作线程完成工作后,通过主线程的Handler处理UI更新,如弹出提示Dialog。可能有些人没有弄明白,Activity都被系统销毁了,工作线程怎么还能调它的变量呢?其实所谓的Activity销毁只是不再受系统的AMS控制,但Activity这个对象的实例还是存在于内存中的,具体什么时候真正把这个对象实例也销毁(回收)了,就要看内存回收机制了,哪怕是这个实例没有可达的引用了也不一定会马上回收。

针对这种用Handler更新UI的情况,我们需要在操作UI前判断一下此Activity是否已被销毁。很多人可能都用过isFinishing()来判断,用多了就会发现好象不太准,因为有时候Activity的生命周期没有按我们预想的来走时(如内存紧张时),会出现判断出错的情况。

所以在判断activity是否被回收时,要在添加一个isDestroyed()的判断。

Q5:Activity如何传递参数,并说说Parcelable和Serializable的区别。

A:使用Intent的Bundle协带参数,就是我们常用的Intent.putExtra方法。

Serializable是Java自带,Parcelable是Android专用。

Serializalbe会使用反射,序列化和反序列化过程需要大量I/O操作。Parcelable自已实现封送和解封,操作不需要用反射,效率要快很多。

6、Activity如何传递数据以及如何进行数据回传

传递数据使用Intent,传输的数据类型包括:基本类型、Bundle、Serializable对象、Parcelable对象。

数据回传使用Activity提供的startActivityForResult(Intent intent,int requestCode)方法。具体使用方式看《Android面试宝典》

7、已调用多个Activity,如何安全退出

1、使用广播,所有开启的Activity都注册有监听此广播的广播接收者,广播接收者收到此类广播后,直接调用finish方法。

2、在Activity的父类当中实现一个集合,在onCreat方法中调用add()方法把启动的Activity加入到集合当中,当退出app时,需要在父类创建一个killAll()方法,在该方法复制一份Activity的集合,遍历集合并销毁Activity。

3、递归退出。使用startActivityForResult()方法打开新的Activity,需要退出时,自定义一个flag标志,在ActivityonActivityResult()方法中处理这个flag,实现递归关闭。

8、如何应对Activity被系统回收

先说说Activity被系统回收的三种情况:

1、内存不足时,后台运行的一些应用程序会被杀死。

2、横竖屏切换时,Activity会被销毁和回收,然后重建

3、长期运行在后台,有时出于省电的目的,会进行回收。

答案就是使用onSavaInstanceState

二、Service

1、功能

Service是一个专门在后台处理长时间任务的Android组件,它没有UI。

Service 是android的一种机制,当它运行的时候如果是Local Service,那么对应的 Service 是运行在主进程的 UI线程上的。如:onCreate,onStart 这些函数在被系统调用的时候都是在主进程的 main 线程上运行的。

如果是Remote Service,那么对应的 Service 则是运行在独立进程的 UI线程上。因此请不要把 Service 理解成线程,它跟线程半毛钱的关系都没有!

2、两种启动方式

  • startService:只是启动Service,启动它的组件(如Activity)和Service并没有关联,只有当Service调用stopSelf()或者其他组件调用stopService()服务才会终止。
  • bindService:该方法启动Service,其他组件可以通过回调获取Service的代理对象和Service交互,而这两方也进行了绑定,当启动方销毁时,Service也会自动进行unBindService()操作,当发现所有绑定都进行了unBindService()时才会销毁Service。

3、Service与Activity怎么实现通信

1、通过Binder对象。Activity调用bindService (Intent service, ServiceConnection conn, int flags)方法,得到Service对象的一个引用,这样Activity可以直接调用到Service中的方法。

2、通过广播。Service向Activity发送消息,可以使用广播,当然Activity要注册相应的接收器。比如Service要向多个Activity发送同样的消息的话,用这种方法就更好。

4、生命周期

Service生命周期

5、Service与Thread

很多时候,你可能会问,为什么要用 Service,而不用 Thread 呢,因为用 Thread 是很方便的,比起 Service 也方便多了,下面就讲解一下。

Thread 的运行是独立于 Activity 的,也就是说当一个 Activity 被 finish 之后,如果你没有主动停止 Thread 或者 Thread 里的 run 方法没有执行完毕的话,Thread 也会一直执行。因此这里会出现一个问题:一方面,当 Activity 被 finish 之后,你不再持有该 Thread 的引用。另一方面,你没有办法在不同的 Activity 中对同一 Thread 进行控制。

因此你可以把 Service 想象成一种消息服务,而你可以在任何有 Context 的地方调用 Context.startService、Context.stopService、Context.bindService,Context.unbindService,来控制它,你也可以在 Service 里注册 BroadcastReceiver,在其他地方通过发送 broadcast 来控制它,当然这些都是 Thread 做不到的。

6、Activity、Intent、Service的关系

一个Activity通常是一个单独的屏幕,每一个Activity都被实现为一个单独的类,这些类都是从Activity基类中继承来的,Activity类显示有视图控件组成的用户接口,并对视图控件的事件做出响应。

Intent的调用是用来进行架构屏幕之间的切换的。Intent是描述应用想要做什么。Intent数据结果中最重要的部分是动作和动作对应的数据,一个动作对应一个动作数据。

Service是运行在后台的代码,不能与用户交互,可以运行在自己的进程,也可以运行在其他应用程序的上下文里。需要通过某一个Activity或其他Context对象来调用。

Activity 跳转到Activity,Activtiy启动Service,Service打开Activity都需要Intent表明跳转的意图,以及传递参数,Intent是这些组件间信号传递者

7、如何保证 Service 在后台不被 kill

1、提升service优先级

在AndroidManifest.xml文件中对于intent-filter可以通过android:priority = “1000”这个属性设置最高优先级,1000是最高值,如果数字越小则优先级越低,同时适用于广播。

2、提升service进程优先级

Android中的进程是托管的,当系统进程空间紧张的时候,会依照优先级自动进行进程的回收。Android将进程分为6个等级,它们按优先级顺序由高到低依次是:

  • 前台进程
  • 可视进程
  • 次要服务进程
  • 后台进程
  • 内容供应节点
  • 空进程

3、onDestroy方法里重启service

service +broadcast 方式,就是当service走ondestory的时候,发送一个自定义的广播,当收到广播的时候,重新启动service;载请联系作者获得授权,非商业转载请注明出处。

Q1:Service的onCreate回调函数可以做耗时的操作吗?

A:不可以。Service的onCreate是在主线程(ActivityThread)中调用的,耗时操作会阻塞UI。

8、Service的混合开启模式

start——bind——unbind——stop

这种模式既保证了服务可以长期运行在后台,又可以让调用者远程调用服务中的方法。

三、BroadcastReceiver

1、功能

BroadcastReceiver 是对发送出来的 广播进行过滤、接收和响应的组件。首先将要发送的消息和用于过滤的信息(Action,Category)装入一个 Intent 对象,然后通过调用 Context.sendBroadcast() 、 sendOrderBroadcast() 方法把 Intent 对象以广播形式发送出去。 广播发送出去后,所有已注册的 BroadcastReceiver 会检查注册时的 IntentFilter 是否与发送的 Intent 相匹配,若匹配则会调用 BroadcastReceiver 的 onReceiver() 方法。

2、两种类型

Broadcast被分为两种:

  • Normal broadcasts 无序广播:会异步的发送给所有的Receiver,接收到广播的顺序是不确定的,有可能是同时。
  • Ordered broadcasts 有序广播:广播会先发送给优先级高(android:priority)的Receiver,而且这个Receiver有权决定是继续发送到下一个Receiver或者是直接终止广播。
  • 本地广播:只在APP内部传播。LoacalBroadcastManager高效的原因主要是因为它内部通过Handler实现,它的sendBroadcast()方法含义并非和我们平时所用的一样,它的它的sendBroadcast()方法其实是通过handler发送一个Message实现的。 既然它内部是通过Handler来实现广播的发送的,那么相比与系统广播通过Binder实现那肯定是更高效了,同时使用Handler来实现,别的应用无法向我们的应用发送该广播,而我们应用内发送的广播也不会离开我们的应用。

3、两种注册方式

  • 静态注册:静态注册即在清单文件中为 BroadcastReceiver 进行注册,使用< receiver >标签声明,并在标签内用 < intent-filter > 标签设置过滤器。这种形式的 BroadcastReceiver 的生命周期伴随着整个应用,如果这种方式处理的是系统广播,那么不管应用是否在运行,该广播接收器都能接收到该广播。
  • 动态注册:动态注册 BroadcastReceiver 是在代码中定义并设置好一个 IntentFilter 对象,然后在需要注册的地方调用registerReceiver()方法,调用unregisterReceiver()方法取消注册,此时就不需要在清单文件中注册 Receiver 了。

4、内部实现机制

1、自定义广播接收者BroadcastReveiver,并复写onReceive()方法

2、通过Binder机制向AMS进行注册

3、广播发送者通过Binder机制向AMS发送广播

4、AMS查找符合相应条件(IntentFilter/Permission等)的BroadcastReceiver,将广播发送到BroadcastReceiver(一般情况是Activity)相应的消息循环队列中

5、消息循环执行拿到此广播,回调BroadcastReceiver中的onReceive()方法

Q1:我们想发送广播只有自己(本进程)能接收到,该如何去做?

A:
1、使用权限,在发送广播时限定有权限(receiverPermission)的接收者才能收到。

2、使用Handler,往主线程的消息池(Message Queue)发送消息,只有主线程的Handler可以分发处理它,广播发送的内容是一个Intent对象,我们可以直接用Message封装一下。在handleMessage时把Intent对象传递给已注册的Receiver。

3、使用LocalBroadcastManager类,其实现方式也是使用Handler,思路和上面也是一样的。

Q2:一个 app 被杀掉进程后,是否还能收到广播?

静态注册的常驻型广播接收器还能接收广播。

四、ContentProvider

  • ContentProvider 为存储和读取数据提供了统一的接口
  • 使用ContentProvider,应用程序可以实现 app 间数据共享
  • Android内置的许多数据都是使用ContentProvider形式,供开发者调用的(如视频,音频,图片,通讯录等)

这个在面试时一般不怎么问,使用过即可,最好写过相关的demo。

1、ContentProvider、ContentResolver、ContentObserver

  • ContentProvider:把一个应用程序的私有数据暴露给其它应用程序

  • ContentResolver:根据ContentProvider提供的URI路径,对数据进行CRUDE操作

  • ContentObserver

五、Intent

Q1: Intent的分类

A1:
1、显式Intent:可以通过类名来找到相应的组件,在应用中用显式Intent去启动一个组件,通常是因为我们知道这个组件(Activity或者Service)的名字。

2、隐式Intent:不指定具体的组件,但是它会声明将要执行的操作,从而匹配到相应的组件。

Intent中包含的属性包括:

  • Component:要启动的组件名称。这个属性是可选的,但它是显式Intent的一个重要属性,设置了这个属性后,该Intent只能被传递给由Component定义的组件。
  • Action:表明执行操作的字符串。它会影响Intent的其余信息,比如Data、Extras。用户可以自定义这个属性,也可以使用系统中已经有的Action值。
  • Data:它是待操作数据的引用URI或者数据MIME类型的URI,它的值通常与Intent的Action有关联。比如,如果设置Action的值为ACTION_EDIT,那么Data的值就必须包含被编辑文档的URI。当我们创建Intent的时候,设置MIME类型非常重要。例如,一个可以显示图片的Activity可能不能播放音频,图片和音频的URI非常类似,如果我们设置了MIME类型,可以帮助系统找到最合适的组件接受Intent。有时候,MIME类型也可以从URI判断出来,例如当Data是一个包含content:字符串的URI时候,可以明确的知道,待处理的数据存在设备中,而且由ContentProvider控制。
  • Category:这个属性是对处理该Intent组件信息的补充。它是一个ArraySet类型的容器,所以可以向里面添加任意数量的补充信息,同时,Intent没有设置这个属性不会影响解析组件信息。
  • Extras:以key-value键值对的形式来存储组件执行操作过程中需要的额外信息,可以调用putExtra()方法来设置该属性,这个方法接受两个参数,一个是key,一个是value。
  • Flags:这个属性可以指示系统如何启动一个Activity,以及启动之后如何处理。例如Activity属于哪一个task(参考Activity的四种启动方式)。

Q2: Intent的使用方法,可以传递哪些数据类型?

A2:通过查询Intent/Bundle的API文档,我们可以获知,Intent/Bundle支持传递基本类型的数据和基本类型的数组数据,以及String类型的数据和String类型的数组数据。而对于其它类型的数据貌似无能为力,其实不然,我们可以在Intent/Bundle的API中看到Intent/Bundle还可以传递Parcelable和Serializable类型的数据,以及它们的数组/列表数据。

所以要让非基本类型和非String/CharSequence类型的数据通过Intent/Bundle来进行传输,我们就需要在数据类型中实现Parcelable接口或是Serializable接口。

Q3:介绍一下Intent、IntentFilter

A3:IntentFilter通常是定义在AndroidManifest.xml文件中,也可以动态设置,通常是用来声明组件想要接受哪种Intent。例如,你如果为一个Activity设置了IntentFilter,你就可以在应用内或者其他应用中,用特定的隐式Intent来启动这个Activity,如果没有为Activity设置IntentFilter,那么你就只能通过显示Intent来启动这个Activity。

六、Fragment

1、为什么被称为第五大组件

有人说View是第五大组件,但是View没有生命周期,而Fragment有生命周期,有了周期就可以灵活的进行处理。

但是他并不是完全独立的,虽然有自己的生命周期,但是还是要依附于Activity,同时被加载到Activity当中。

2、Fragment加载到Activity的两种方式

1、静态加载

在XML文件中添加Fragment到Activity的布局文件中。

2、动态加载

使用FragmentManager管理所有要启动的Fragment,
并用FragmentTransaction来添加或替换Fragment,
并用容器资源来作为标志位,设置Fragment将要显示到Activity当中的位置,
最后调用commit方法来完成整个步骤。

3、FragmentPagerAdapter与FragmentStatePagerAdapter的区别

FragmentPagerAdapter适用于页面较少的情况,FragmentStatePagerAdapter则适用于页面较多的情况。

4、Fragment的生命周期

Fragment生命周期a

Fragment生命周期b

5、Fragment之间的通信

Fragment与Activity

在Fragment中调用Activity中的方法:getActivity()

Fragment与Fragment

在Fragment中调用Fragment中的方法:先调用getActivity(),然后调用findFragmentById()

Activity与Fragment

若activity中包含自己管理的Fragment的引用,则可以直接访问Fragment的公有方法。若没有,则通过getFragmentManager().findFragmentById()获得相应的实例,然后进行操作。

6、Fragment管理器:FragmentManager

  • add():将Fragment实例添加到Activity的最上层
  • replace():替换Fragment的实例,而不是直接将实例添加到最上层
  • remove():

7、Fragment的切换

开发的时候,有时候Fragment的切换,是不需要对原先的Fragment进行重新加载的。而Fragment的界面是既可以进行重新加载,也可以不进行重新加载。
每次重新加载的话,我们是使用的replace来进行fragment的替换的。
如果,不对fragment的数据进行重新加载的话,那么就用add来添加fragment,显示的时候用show,切换的时候用hide掉当前的,show切换的目标。

8、Fragment事务

什么是“事务”,一直不明白,不懂。看了《Android面试宝典》,上面说:事务指的就是一种原子性、不可拆分的操作。所谓的Fragment事务,就是对Fragment进行添加、移除、替换或执行其它动作,提交给Activity的每一个变化,这就是Fragment事务。

七、Context

参考文章:Context都没弄明白,还怎么做Android开发?

1、为什么不能 new Activity()

Android程序不能像Java程序一样,随便创建个类,写个Main()方法就能跑了。Android应用模型是基于组件的应用设计模式,组件的运行要有一个完整的Android工程环境,在这个环境下,Activity、Service、BroadcastReceiver等系统组件才能正常工作,而这些组件并不能采用普通的Java对象创建方式,new一下就能创建实例了,而是要有它们各自的上下文环境,也就是Context。

2、Context的继承关系

Context继承关系

Context的两个子类分工明确,其中ContextImpl是Context的具体实现类,ContextWrapper是Context的包装类。

Activity、Application、Service虽然都继承自ContextWrapper,但Context的具体实现类是ContextImpl,所以它们的初始化过程都会创建ContextImpl对象有ContextImpl实现Context中的方法。

BroadcastReceiver、ContentProvider并不是Context的子类,它们所持有的Context都是其它地方传过来的,所以不计入Context总数。

一个应用程序中的:Context数量 = Activity数量 + Service数量 + 1(一个Application)

3、生动形象的理解Context

一个Android应用程序,可以理解为一部电影或者一部电视剧,Activity,Service,Broadcast Receiver,Content Provider这四大组件就好比是这部戏里的四个主角。他们是由剧组(系统)一开始就定好了的,整部戏就是由这四位主演领衔担纲的,所以这四位主角并不是大街上随随便便拉个人(new 一个对象)都能演的。有了演员当然也得有摄像机拍摄啊,他们必须通过镜头(Context)才能将戏传递给观众,这也就正对应说四大组件(四位主角)必须工作在Context环境下(摄像机镜头)。那Button,TextView,LinearLayout这些控件呢,就好比是这部戏里的配角或者说群众演员,他们显然没有这么重用,随便一个路人甲路人乙都能演(可以new一个对象),但是他们也必须要面对镜头(工作在Context环境下),所以Button mButton=new Button(Context)是可以的。

4、Context的作用域

Context作用域

从上图我们可以发现Activity所持有的Context的作用域最广,无所不能。因为Activity继承自ContextThemeWrapper,而Application和Service继承自ContextWrapper,很显然ContextThemeWrapper在ContextWrapper的基础上又做了一些操作使得Activity变得更强大。

而且我们可以总结,凡是涉及UI的操作都要在Activity的环境中来执行。

5、Application Context 和 Activity Context 异同

1、Application-Context的生命周期是整个应用,所以,对于它的使用必须慎重,大部分情况下都要避免使用它,因为它会导致内存泄露的问题。

如果我们现在在一个Activity中引入一个Application-Context,那么,当我们这个Activity关闭的时候,这个Application-Context是不会消失的,因为它的生命周期要比我们的Activity长,如果只是一些用来计算的数据还好,但是如果这个Context与我们的Activity的创建有关,或者与我们在Activity要销毁的资源比如图片资源有关,那么,问题就大条了!因为我们的Activity或图片就不能正常销毁,因为它与Application-Context相关联,如果不能正常的释放掉与它们相关的内存,就会出现所谓的内存泄露的问题。这种问题有时候是非常隐晦的,以至于我们根本无法察觉到,所以我们必须遵守相关的使用原则。

2、Activity Context的生命周期是和得到它的引用的Activity一样长,如果这个Activity结束了,那么,这个Context也会得到释放。它并不像我们上面的Application-Context需要特意去获得,可以在一个Activity中使用this就可以获得当前Activity的Context。

八、HandlerThread

Android实现多线程的几种方式

  • Thread、Runnable
  • Handler
  • AsyncTask
  • HandlerThread
  • IntentService
  • 线程池

1、介绍

HandlerThread继承于Thread,所以它本质就是个Thread(thread+handler+looper)。与普通Thread的差别就在于,它不仅建立了一个线程,并且创立了消息队列,有自己的looper,可以让我们在自己的线程中分发和处理消息,并对外提供自己这个Looper对象的get方法。

传统的Thread在任务结束后,线程就会被自动销毁,倘若我们又要创建一个新的任务,就不得不重新创建Thread,这样的不断的创建和销毁操作是非常消耗系统资源的。

HandlerThread自带Looper使他可以通过消息队列,来重复使用当前线程,当有耗时任务时,就会执行该任务,没有任务时,循环线程就会处于阻塞状态,等待新的任务,节省系统资源开销。这是它的优点也是缺点,每一个任务都将以队列的方式逐个被执行到,一旦队列中有某个任务执行时间过长,那么就会导致后续的任务都会被延迟处理。

与线程池注重并发不一样,Handler是一个串行队列,因为它背后只有一个线程,当然相对于线程池,它更安全了,因为它不涉及线程间数据的交互问题。

2、使用方法

自己写。

九、IntentService

1、概念

IntentService是继承并处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动IntentService的方式和启动传统的Service一样。

1、当任务执行完后,IntentService会自动停止,而不需要我们手动去控制或stopSelf()。

2、另外,可以启动IntentService多次,而每一个耗时操作会以工作队列的方式在IntentService的onHandlerIntent回调方法中执行,并且,每次只会执行一个工作线程,执行完第一个再执行第二个。所以总结优点:

1、一方面不需要自己去new Thread

2、另一方面不需要考虑在什么时候关闭该Service

2、使用方法

自己写

十、AsyncTask

参考

最后修改:2020 年 06 月 14 日 01 : 32 PM
如果觉得我的文章对你有用,请随意赞赏