<>什么是Intent


翻译就是意图,就是你想做的事情,比如我想成为资深攻城狮,具体的就是在Activity中我想跳转到下一个Activity中,或者我想开启服务,我想发送广播,都是需要用到Intent(意图)的。

<>理解

就是你想做的事,列如跳转到对应的活动,开启服务,发送广播等等。

<>类型

意图类型 定义 用于
显式意图 调用Intent.setComponent()或Intent.setClass()方法明白指定了组件名的Intent为显式意图 一般内部
隐式意图 没有明白指定组件名的Intent为隐式意图 一般外部
注:
没有绝对的用于内外部之分,显示意图可通过(包名,Activity的完整类路径)访问其它应用。
另外,Android 5.0以后规定必须显式启动Service。

<>1.显式意图

调用Intent.setComponent()或Intent.setClass()方法明白指定了组件名得Intent为显式意图。
如:
Intent intent = new Intent(); intent.setAction(Activity1.this,Activity2.class);
intent.putExtra("name",name);//通过意图传递数据 startActivity(intent);
其中还包括通过包名去启动
Intent intent = new Intent(); intent.setClassName("待启动Activity的包名",
"待启动Activity的完整类路径")//包名getPackageName() intent.putExtra("name",name);//通过意图传递数据
startActivity(intent);//跳转到另一个Activity
如何接收传过来的数据呢?
Intent intent1=getIntent();//获取传递过来的意图 intent.getStringExtra("name");
//获取前一个Activity传递过来的数据
其中还包括回调数据式传值跳转:startActivityForResult()方法
Intent _intent = new Intent(MainActivity.this,TwoActivity.class); intent.
putExtra(key, value); // 第二个参数是请求码,只要是一个唯一值 startActivityForResult(intent, 1234)
;
我们在看看TwoActivity.class中的回传数据的代码
Intent intent = new Intent(); intent.putExtra("name","张三"); setResult(RESULT_OK
,intent); this.finish();
数据回传之后肯定我们的MainActivity.class中要有接收的方法,我们看看接收方法onActivityResult()
@Override protected void onActivityResult(int requestCode, int resultCode,
Intent intent) { switch (requestCode) { case 1234: if (resultCode == RESULT_OK)
{ String name= intent.getStringExtra("name"); Log.d(TAG, "onActivityResult: "+
name); } break; default: }
onActivityResult()方法带有三个参数,
第一个参数requestCode,即我们在启动活动时传入的请求码。
第二个参数resultCode,即我们在返回数据时传入结果码。
第三个参数data,即携带着返回数据的Intent。

由于在一个活动中有可能调用startActivityForResult()方法去启动很多不同的活动,每一个活动返回的数据都会回调到onActivityResult()这个方法中,因此我们首先要做的就是通过检查requestCode的值来判断数据来源。确定数据是从TwoActivity返回的之后,我们再通过resultCode的值来判断处理结果是否成功。最后从data中取值并打印出来,这样就完成了向上一个活动返回数据的工作。

<>上面讲的是两种简单的数据intent传递方式,那如果数据多怎么办,没事我们可以用到序列化,绑定Bundle 对象进行处理
<>1.两种方式 Bundle.putSerializable(Key,Object); //实现Serializable接口的对象 Bundle.
putParcelable(Key, Object); //实现Parcelable接口的对象 <>2.步骤
1.创建序列化类

Book.class,其中要重新的方法很多,但我还是推荐大家用Parcelable,因为它比Serializable在内存消耗上要少太多了,作为攻城狮怎么可以偷懒去使用Serializable?Serializable的使用很简单,直接实现接口就行,不想Parcelable要重写很多方法。
public class Book implements Parcelable{ private String bookName; private
String author; private int publishDate; public Book(){ } public String
getBookName(){ return bookName; } public void setBookName(String bookName){ this
.bookName = bookName; } public String getAuthor(){ return author; } public void
setAuthor(String author){ this.author = author; } public int getPublishDate(){
return publishDate; } public void setPublishDate(int publishDate){ this.
publishDate= publishDate; } @Override public int describeContents(){ return 0; }
@Override public void writeToParcel(Parcel out, int flags){ out.writeString(
bookName); out.writeString(author); out.writeInt(publishDate); } public static
final Parcelable.Creator<Book> CREATOR = new Creator<Book>(){      @Override
public Book[] newArray(int size){ return new Book[size]; } @Override public Book
createFromParcel(Parcel in){ return new Book(in); } }; public Book(Parcel in){
//如果元素数据是list类型的时候需要: lits = new ArrayList<?> in.readList(list);
否则会出现空指针异常.并且读出和写入的数据类型必须相同.如果不想对部分关键字进行序列化,可以使用transient关键字来修饰以及static修饰.
bookName= in.readString(); author = in.readString(); publishDate = in.readInt();
} }
2.再看看我们传递和接收的代码
//传递 Book book = new Book(); book.setBookname("Darker"); book.setBookauthor(
"me"); book.setPublishDate(20); Bundle bundle = new Bundle(); bundle.
putParcelable("book", book); Intent intent = new Intent(MainActivity.this,
AnotherActivity.class); intent.putExtras(bundle); //接收 Intent intent = getIntent
(); Bundle bun = intent.getExtras(); Book book = bun.getParcelable("book"); Log.
d(TAG, "AnotherActivity: "+book);
显式意图工作原理:
就是从当前上下文跳转到指定活动,或者启动指定服务,发送指定广播。

显式意图非常easy。此处就不再赘述。

<>2.隐式意图


没有明白指定组件名得Intent为隐式意图。android系统会依据隐式意图中设置的动作(action)、类别(category)、数据(URI和数据类型)找到最合适的组件来处理这个意图。

如调用电话拨号:
Intent intent = new Intent(); intent.setAction("android.intent.action.CALL");
intent.setData("Uri.parse("tel:") + mobile");//mobile为电话号码(是数字) startActivity(
intent);
通过动作名称(可自定义):
<intent-filter> <action android:name="android.intent.yinsiyitu.action"/> <
category android:name="android.intent.category.DEFAULT"/> <data android:mimeType
="application/person"/> <data android:scheme="jianren" android:host=
"www.ggl.com"/> </intent-filter>
调用方式
Intent intent = new Intent(); intent.setAction(
"android:intent.yinsiyitu.action"); intent.addCategory(Intent.CATEGORY_DEFAULT);
//intent.setData(Uri.parse(jianren://www.ggl.com));//会清除前面所有set的type
//intent.setType("application/person");//会清除前面所有的set的data
//这是setData和setType两全的方法,另外如果上面的Activity定义了host,则这里一定也要指定 intent.setDataAndType(
Uri.parse("jianren://www.ggl.com"),"application/person");
//如果上面的Activity没有定义host,则Uri.parse("jianren:");至少要写到冒号,不可以只写Uri.parse("jianren")
startActivity(intent);
注:

若intent.setDataAndType(Uri.parse(“jianren://www.ggl.com”),“application/person”);

分开写,即:intent.setData(),intent.setType()(括号里的东西略)时,就算是都匹配也会报错。

原因:在setType()文档中有一句话。This method automatically clears any data that was
previously set by setData(Uri).也就是说。当设置了setType时会自己主动清除setData中的内容。

所以。解决方法:写成intent.setDataAndType(Uri.parse(“itcast://www.itcast.cn/person”),
“image/gif”);这样就正确了。

工作原理:

当您隐式地启动一个service或activity时,Intent会根据其中的内容,匹配其他组件中manifest文件的Intent-filter,启动符合条件的组件,并把Intent中的参数传过去,如果有多个intent-filter满足条件,那么系统会弹出一个对话框,由用户决定启动哪个组件。

*
首先Activity A利用传入的Intent调用startActivity();

*
系统会根据该Intent的条件搜索Android系统中所有匹配的组件。

*
若找到了匹配intent的intent-filters所属的组件(Activity
B),则启动该组件,并回调onCreate()方法,同时将Intent传递过去。intent-filters是manifest文件中组件内部的一个标签,该标签描述了组件具备什么特性,如果您未配置intent-filters,那个该组件只能被显式启动。

<>Intent使用要求

<>创建Intent对象(Building an Intent)

Intent中包含了目标组件需满足的特性。Intent中应包含以下信息:
目标组件的名字。

*
对于显式启动,这是不可缺省的,您可以使用Intent的构造方法传入组件名称,也可以调用setComponent(), setClass(),
setClassName()这些方法传入组件名;

*
若是隐式启动,这是可选的,但intent应包含其他信息(action、category、data);

<>隐式启动中的action


是一个可以指明目标组件行为的字符串。action很大程度上决定了category和data中应传入的信息;您也可以在自己的应用程序组件中指定action,以便让其他应用程序启动自己的组件。对应action中字符串,不建议使用硬编码的形式,而应在所属组件的类中设置为常量。

常见的action有:

*
ACTION_VIEW:用ACTION
_VIEW启动的activity一般可以向用户展示一些信息,比如启动一个相册APP中展示图片的activity,或是启动一个地图APP中展示地址信息的activity。

*
ACTION_SEND:一般需要向通过ACTION _SEND启动的activity
附带着发送一些信息,这些信息由由目标activity决定该发送给谁,比如社交类APP或是发送邮件的APP。

您可以将action作为参数传入Intent的构造方法或setAction()方法中。

如需定义在自己的组件中定义action,应以应用的包名作为前缀,比如:
staticfinalStringACTION_TIMETRAVEL=”com.example.action.TIMETRAVEL”;

<>隐式启动中的data


一个URI对象是一个引用的data的表现形式,或是data的MIME类型;data的类型由Intent的action决定,比如说若action是ACTION_EDIT,那么data的URI应指向一个可编辑的文件。


当创建一个Intent时,除了为data指定URI以外,还应该指定data的MIME类型,比如说,一个用于展示图片的activity是不能用来放音乐的,如果您要启动这个activity,就需要将data的MIME类型指定为"image/png"、"image/jpeg"等。有些时候,从data的URI中就能推断出MIME的类型,比如当一个URI的schema是"content://"时,表明该URI指向了设备内部的一个文件并由ContentProvider管理着,系统可以根据该文件推断出data的MIME类型。


您可以调用setData()方法设置URI,调用setType()方法设置MIME类型,或调用setDataAndType()方法同时设置URI和MIME类型。

请注意:
如果您需要同时设置URI和MIME类型,只能调用setDataAndType()方法,而不能分别调用setData()和setType(),因为调用setData()时会首先将setType()中的内容置空,反之亦然(
they each nullify the value of the other)
上面有提到再强调一下。

<>隐式启动中的category

是一个字符串,表示目标组件的附加信息,大部分intent不需要category。以下是依稀而常用的category:

* CATEGORY_BROWSABLE:表示目标activity可以被网页上的某个链接启动,如图片activity或e-mail信息activity。
* CATEGORY_LAUNCHER:目标activity是任务栈的第一个activity,也就是应用程序的启示activity。
您可以将category参数传入addCategory()方法中

<>总结

目前博主也就学到了这些,因为我感觉够用,我后续的成长中我会更深入的学习并分享给大家
这篇博客借鉴了很多官方文档原文。
个人也是推荐Android初学者看官网文档,虽然这很艰苦,但是这具有权威性的文档,是你想成为Android高级攻城狮的必经之路
和我一起加油吧,与你共勉。

付:
Intent官方文档
<https://developer.android.google.cn/guide/components/intents-filters>

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信