引言

  Intent,意图,主要解决Android各项组件之间的通讯问题。Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用。因此,Intent在这里起着一个媒体中介的作用,专门提供组件互相调用的相关信息,实现调用者与被调用者之间的解耦。
  而Intent又分为两种,显式Intent(Explicit intent)隐式Intent(Implicit intent)。这篇文章主要就来介绍一下这两种Intent。

启动模式

  Intent作为我们Android程序员经常要面对的一个组件,最常用的就是去启动一个Activity了,所以在这里我们就先拓展一下Activity的四种启动模式。
(1)standard:每次激活Activity时(startActivity),都创建Activity实例,并放入任务栈;这个是系统默认的启动模式;
(2)singleTask:如果要激活的那个Activity在任务栈中存在该实例,则不需要创建,只需要把此Activity放入栈顶,并把该Activity以上的Activity实例都pop(弹出销毁);这个模式可以用来退出整个应用。将主Activity设为SingTask模式,然后在要退出的Activity中转到主Activity,然后重写主Activity的onNewIntent函数,并在函数中加上一句finish。(因为Activity不创建,所以不会进入onCreate函数,只会进入onNewIntent函数)。
(3)singleInstance:如果应用1的任务栈中创建了MainActivity实例,如果应用2也要激活MainActivity,则不需要创建,两应用共享该Activity实例;
此启动模式和我们使用的浏览器工作原理类似,我们都知道在多个程序中访问浏览器时,如果当前浏览器没有打开,则打开浏览器,否则会在当前打开的浏览器中访问。此模式会节省大量的系统资源,因为他能保证要请求的Activity对象在当前的栈中只存在一个。
(4)singleTop:如果在任务的栈顶正好存在该Activity的实例, 就重用该实例,否者就会创建新的实例并放入栈顶(即使栈中已经存在该Activity实例,只要不在栈顶,都会创建实例)。
在每次使用新的Activity时会自动检测栈顶的当前Activity是否是需要引用的Activity,如果是则直接引用此Activity,而不会创建新的Activity;当它不需要创建新的Activity对象时,它会调用onNewIntent()方法。

任务栈:每个应用都有至少一个任务栈,是用来存放Activity的,功能类似于函数调用的栈,先后顺序代表了Activity的出现顺序;比如Activity1–>Activity2–>Activity3,则任务栈为:

好,下面我们进入正文。

显式Intent

显式,顾名思义,就是明显指出了目的组件,有以下三种启动方式:
1.构造方法传入目标组件,这也是我们最常用的方式

2.setComponent方法

3.setClass/setClassName方法

显式Intent通过设置目标Component来调用需要前往的组件,可以直接确定一个目标组件,意图明确,所以称之为显式Intent。设置这个类的方式可以是Class对象(如IntentDemo2Activity.class),也可以是包名加类名的字符串(如”com.jyx.demo.myapplication.IntentDemo2Activity”)。这个很好理解,在应用程序内部跳转界面常用这种方式。

隐式Intent

隐式Intent,就是并不直接指明目标组件,而是通过设置Action、Data、Categroy,然后让系统来筛选出来符合条件得组件,筛选是根据所有的来筛选。例如:

AndroidManifest.xml文件中,首先被调用的Activity要有一个带有并且包含的Activity,设定它能处理的Intent,并且category设为”android.intent.category.DEFAULT”。action的name是一个字符串,可以自定义,例如我在这里设成”testIntent”

然后我们就可以在IntentDemoActivity中这么写来调用IntentDemo2Activity

1.setAction方法

2.直接在构造方法里设置

通过在AndroidManifest.xml里设置Action,来表明自己的意图,其他Activity就可以通过Intent找到这个Activity并启动。除了自己可以设置Action,Android还为我们提供了许多系统常用界面的Action,如下:

  需要注意的是,定义了Action的Activity,其他应用程序也可以调用,这样一来,程序之间的交流就很容易了,比如手机qq可以调用qq空间。所以,为了防止程序之间一些意料之外的影响,我们定义Action就要更详细更复杂一些,一般是包名+Action名,上面我用的“testIntent”就不太合理了,应该改成“com.jyx.demo.myapplication.testIntent”;同理,你也可以在自己的程序中调用其他程序的Action,比如在自己的程序中调用拨号面板:

  此外,一个Activity可以处理多种Action,当然你的程序必须有足够的功能,Intent的Action只要是其中之一,就可以打开这个Activity。

  对于一个Action字符串,系统有可能会找到一个Activity来处理,也可能找到多个,当然也有可能一个也找不到:
1.找到一个Activity
这样的话就直接打开这个Activity,无需多言。
2.找到多个Activity
这样的情况下,系统就会提示从多个Activity中选择一个打开,比如我再自己的程序里设置Action为:
“android.intent.action.DIAL”,这样别的程序调用拨号器时,系统就会询问,用哪一个。如下:

3.一个Activity都没找到
一个Activity都没找到的话,程序就会报错,会抛出ActivityNotFoundException。比如我们随便写一个Action:

所以要注意捕捉异常:

或者也可以用resoleActivity方法判断能否找到合适的Activity,如果没有,就停止startActivity

注意resolveActivity方法返回值就是显式Intent上面讲到的ComponentName对象,一般情况下也就是系统找到的那个Activity。但是如果有多个Activity可供选择的话,则返回的Component是com.android.internal.app.ResolverActivity,也就是用户选择Activity的那个界面对应的Activity,这里不再多说。

以上就是我对显式Intent和隐式Intent的介绍,以后可能会出关于Intent的更多介绍,欢迎大家一起交流。

最后,欢迎指正,感谢阅读。

Tagged:

发表评论

电子邮件地址不会被公开。 必填项已用*标注