三大组件间信使Intent的再学习

意图对象:要做什么 信使对象:封装并传递数据
Intent的调用是用来进行架构屏幕之间切换的,Intent是描述应用想要做什么。
Intent数据结构中二个最重要的部分是动作和动作对应的数据,一个动作对应一个数据;
Activity跳转到Activity,Activity启动Service,Service打开Activity都需要Intent表明跳转的意图,
以及传递参数,Intent是这些组件间信号传递的承载者;
一个android应用程序由多个组件组成,每个组件之间使用Intent进行通信,Intent可以译为“意图、目的”的意思;它是Activity、Service和BroadCast Receiver三大组件之间相互激活的手段;Intent是android程序中传输数据的核心对象;在android的官方文档中对Intent的定义是:执行某操作的一个抽象描述;在一个android程序中,主要是由三种组件组成的,这三种组件是独立的,他们之间可以相互调用、协调工作,最终组成一个真正的android程序;在这些组件之间的通信中,主要是由Intent协助完成的,Intent负责对应用程序中一次操作的动作、动作涉及的数据以及附加数据进行描述,android则根据此Intent的描述,负责找到对应的组件,将Intent传递给调用的组件,并完成组件的调用。因此Intent在这里起着一个媒体中介的作用,专门提供组件相互调用的相关信息,实现调用者与被调用者之间的解耦。例如在一个联系人维护的应用程序中,当在一个联系人列表屏幕(假设对应的Activity为listActivity)上单击某个联系人后,希望能够跳到此联系人的详细信息屏幕(假设对应的Activity为detailActivity)。为了实现这个目的,listActivity需要构建一个Intent,这个Intent用于告诉系统:要做“跳转查看动作”,而此动作对应的查看对象是“某联系人”;然后调用startActivity(Intent intent)方法将构造的Intent传入,系统会根据该Intent中的描述,在AndroidManifest.xml文件中找到满足此Intent要求的activity,即detailActivity,并将Intent传入;最后detailActivity会根据此Intent中的描述执行相应的操作。下面对Intent对象和其常见的三种传输机制进行介绍:Intent对象主要用来在Android程序的Activity、Service和BroadcastReceiver这三大组件之间传输数据,而针对这三大组件有独立的Intent传输机制:
Activity:通过将一个Intent对象传递给Context.startActivity()或Activity.startActivityForResult(),启动一个活动或者使一个已经存在的活动去做新的事情;
Service:通过将一个Intent对象传递给Context.startService(),初始化一个Service或者传递一个新的指令给正在运行的Service;类似地,通过将一个Intent传递给Context.bindService(),可以建立调用组件和目标服务之间的连接;
BroadcastReceiver:通过将一个Intent对象传递给任何广播方法(如Context.sendBroadcast()、Context.sendOrderedBroadcast()、Context.sendStickyBroadcast()等,
都可以传递到所有感兴趣的广播接收器;

在每种传输机制下,android程序会自动查找合适的Activity、Service或者BroadcastReceiver来响应意图;
一个intent对象实质上是一个捆绑的信息,包含对intent有兴趣的组件的信息(如要执行的动作和要作用的数据)、android系统有兴趣的信息(如处理intent组件的分类信息和如何启动目标活动的指令等);
1、意图分两类: 显式意图(应用程序的内部调用)和隐式意图(一般用于跨程序启动组件时用)
2、六大属性:其中跟要启动的目标组件有关系的有前四个
ComponentName component 显式意图 明确指定了要启动的目标组件是谁
组件名类型 知道要启动那个组件对象 用于描述目标组件名
如果intent对象中含有一个完整的componentName属性,那么我们认为这个intent对象是一个显式意图
如果在创建意图时没有给component赋值,而是给下面三个属性赋值就是隐式意图;
隐式意图就是启动的意图有了,但没有明确指定要启动的目标组件具体是谁,只给出了动作条件;
如手机里的组件选择 目标过滤:必然得有一个匹配筛选过滤的过程
一方是意图(包含以下三大意图),一方是组件在声明时所声明的过滤器
具体是用你创建的隐式意图的三个属性逐项与你声明组件时的intent-filter
的三个相应属性进行一一比较;所有项都匹配通过才可以;
intent-filter中可以配置如下三个隐式属性:
String action 隐式意图 用于描述目标组件可以执行的动作 如要动作是可以查看网页、会做饭、会吃饭 但是只能筛选一个动作
Uri data 隐式意图 这个动作指向的数据 如要查看网页的网址 描述目标组件可以处理的数据类型
其他二个隐式意图只有name属性 data属性还有如下三个属性(都是uri的属性)
mimetype描述的是一个可以处理的数据类型 image/jpeg
如果有该属性的设置 启动时必须得有intent.setType(”image/jpeg”)才能启动成功
scheme: file
host:
port:
这样就需要设置:intent.setDataAndType(Uri.parse(“file:///mnt/sdcard/xx.jpeg”),”image/jpeg”);
uri 统一资源标示符(实质是封装了符合uri格式的字符串)
可以访问任何机器上的某一个资源、一个文件
http://root@localhost:8080/appname/path/name=zs&&pwd=123 #segment
scheme: http
user: root
host: localhost
port: 8080
authority: root@localhost:8080
ContentProvider注册时在android大环境中的标示 ContentReslover访问时用
path: appName/path
query: name=zs&pwd=1234
segment: #segment
String…category隐式意图 字符串数组或集合 动作类型 描述目标组件所属的分类
她是属于大眼睛的、长头发的 这个可以有多个
启动隐式意图时只要是人家筛选条件子集就可以实现启动;
Bundle extras 键值对集合
用来传递参数的键值对集合 intent传递的所有键值对集合都是存在这里面的
用于使用Intent从第一个组件把数据传递给第二个组件.
int flags 在目标组件启动之前所设定的标记值;根据标记值的不同,我们可以在activity等组件启动的时候有不同的表现;
Activity可以启动service,但是service能够启动Activity吗?只能是界面启动界面,service没有界面,突然启动有界面的activity,那么activity该放在哪个任务栈中呢?它没有所属任务栈了;所以在任何非activity中启动activity都要设置flags; 启动目标组件时使用的启动模式
Intent intent = new Intent(this,MainActivity.class);
Intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//启动标记里明确指定这个新启动的Activity将创建在一个新的任务栈里
startActivity(intent);

3、构造方法 Intent()
Intent(Context context,Class class)//上下文对象、目标组件的类对象
Intent(String action)
Intent(String action, Uri data)
4、主要方法:
void setComponent(ComponentName component)
ComponentName getComponent()
void setClass(Context context,Class cls)
void setClassName(Context context,String clsName)
void setClassName(String pkgName,String clsName)
void setAction(String action)
String getAction()
void addCategory()
Set getCategories()
void setData(Uri data)
Uri getData()
void putExtras(Bundle extras)
Bundle getExtras()
void putExtra(String key,byte value)

byte getByteExtra(String key,byte defaulValue)

void setFalgs(int flag)
int getFlags()

适用于隐式意图:
action: 用于描述目标组件可以执行的动作
Intent intent=new Intent();
intent.setAction(“xxxxx”);
startActivity(intent);





action的匹配原则:Intent对action的测试方式:
intent对象中可以包含最多一个action set基本都是单属性设置
一个启动目标的动作只能有一种 也就是对于一个意图只能有一种明确的动作
Intent中只能含有1个action;
在intent-filter中可以声明多个action
而反过来对于一个组件是可以接收多种动作的
3、如果intent对象中的action在intent-filter声明的范围之内
则该intent对象通过intent-filter的action测试
4、如果intent-filter中未声明任何的action,则该intent-filter默认
拒绝所有的action测试
5、如果intent对象中不包含action,则默认能够通过所有的action测试
除非intent-filter中也未声明action android中拒绝优先
动作Action很大程度上决定了intent如何构建,特别是数据data和附加信息extras信息,就像一个方法名决定了参数和返回值一样,正是由于这个原因,所以应该尽可能明确指定动作,并紧密关联到其他intent字段。也就是说,应该定义组件能够处理的intent的整个协议,二不仅仅是单独地定义一个动作,在intent类中,定义了一系列动作常量,其目标组件包括Activity和Broadcast二类;

Intent对Category的测试: Category 用于描述目标组件所属分类 动作类型
系统自带的category:
Intent.CATEGORY_DEFAULT;
Intent.CATEGORY_APP_CONTACTS;
Intent.CATEGORY_APP_MAPS;







Intent i=new Intent();
i.addCategory();
startActivity(i);
1、intent对象中可以包含多个category 即一个动作可以属于多种动作类型
2、在intent-filter中也可以声明多个category
3、如果intent中包含的category是intent-filter中声明的category
的子集,则intent通过该intent-filer的category测试
4、如果intent对象中不包含任何的category,则可以通过所有的category测试
5、如果创建一个新Intent对象,那么该对象中将会被自动追加一个Category:
android.intent.category.DEFAULT
注意:所有传入到startActivity方法中的intent对象都会被自动追加一个category
——Intent.CATEGORY_DEFAULT
Intent.CATEGORY_DEFAULT(android.intent.category.DEFAUL)
所以要想支持隐式意图的组件在声明时必须得有category,不然它会拒绝所有隐式意图;
data: 用于描述目标组件可以处理的数据类型
Intent i=new Intent(action);
i.setData(uri);
Intent对Data的测试
Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED);//媒体卡装载成功
intent.setData(Uri.parse(“file://”+Environment.
getExternalStorageDirectory().getAbsolutePath()));//把路径传进去
sendBroadcast(intent);
intent对象中包含的数据是一个具体的Uri对象 (data)
intent对象中可以含有1个具体的Data(Uri)
在intent-filter中声明该组件所能支持的数据的Uri格式(四项有递进原则)

协议 android:scheme 主机地址android:host
端口号android:port 路径 android:path
媒体类型 android:mimeType
Intent.setData(Uri.parse(“http://www.163.com”));

3、如果intent对象中的Uri数据符合 intent-filter 中声明的匹配格式
则该intent对象通过intent-filter的data测试
4、若intent-filter中含有data的要求,那么intent
对象必须包含data数据, 才可以运行目标组件.
5、如果intent-filter中配置了mimetype,那么intent对象中必须设置了uri与
mimetype才可以正常访问;
这里写图片描述
这里写图片描述
调用与被调用:我们的通信使者Intent
Intent意图用于应用程序间进行交流,打个电话来都会发Intent, 这个是Android架构的松耦合的精髓部分,
大大提高了组件的复用性,比如你要在你的应用程序中点击按钮,给某人打电话,很简单看下代码先:
Java代码
Intent intent = new Intent();
intent.setAction(Intent.ACTION_CALL);
intent.setData(Uri.parse(“tel:” + number));
startActivity(intent);
  扔出这样一个意图,系统看到了你的意图就唤醒了电话拨号程序,打出来电话。什么读联系人,发短信啊,邮件啊,统统只需要扔出intent就好了,这个部分设计地确实很好。
  那Intent通过什么来告诉系统需要谁来接受他呢?
通常使用Intent有两种方法,第一种是直接说明需要哪一个类来接收代码如下:
Java代码
Intent intent = new Intent(this, MyActivity.class);
intent.getExtras().putString(“id”, “1”);
startActivity(intent);
  第一种方式很明显,直接指定了MyActivity为接受者,并且传了一些数据给MyActivity,
在MyActivity里可以用getIntent()来得到这个intent和数据。
第二种就需要先看一下AndroidMenifest中的intentfilter的配置了
Xml代码






< /intent-filter>
  这里面配置用到了action, data, category这些东西,那么聪明的你一定想到intent里也会有这些东西,
然后一匹配不就找到接收者了吗? action其实就是一个意图的字符串名称。
  上面这段intent-filter的配置文件说明了这个Activity可以接受不同的Action,当然相应的程序逻辑也不一样咯,提一下那个 mimeType,他是在ContentProvider里定义的,你要是自己实现一个ContentProvider就知道了,必须指定mimeType才能让数据被别人使用。
  不知道原理说明白没,总结一句,就是你调用别的界面不是直接new那个界面,而是通过扔出一个intent,让系统帮你去调用那个界面,这样就多么松藕合啊,而且符合了生命周期被系统管理的原则。想知道category都有啥,Android为你预先定制好的action都有啥等等,请亲自访问官方链接Intent ;想知道怎么调用系统应用程序的同学,可以仔细看一下你的logcat,每次运行一个程序的时候是不是有一些信息比如:
Starting activity:Intent{
action=android.intent.action.MAIN categories={android.intent.category.LAUNCHER} flags=0x10200000 comp={com.android.camera/com.android.camera.GalleryPicker}
}
  再对照一下Intent的一些set方法,就知道怎么调用咯;
隐式、显式Intent的区别:
显示意图:通过名字指明目标组件(这个组件名字字段component name field, 前面提到过, 有一个数值集)。既然组件名称通常不为其他应用程序的开发者所了解,显式意图典型的被用作应用程序的内部消息-例如一个活动启动一个附属服务或姊妹活动。
隐式意图:不命名目标组件(组件名称字段为空)。隐式意图经常用来激活其他应用程序的组件。这一块参考Intent说明,可以同时看一下Notepad的例子,帮助理解,个人感觉很重要!

通过Intent传递一些二进制数据的方法有哪些?
1). 使用Serializable接口实现序列化,这是Java常用的方法。
2). 实现Parcelable接口,这里Android的部分类比如Bitmap类就已经实现了,
同时Parcelable在Android AIDL中交换数据也很常见的。

适用于显式意图: ComponentName
ComponentName n1= new ComponentName(this, MainActivity.class);
ComponentName n2= new ComponentName(this, “com.example.android_day16_intent.MainActivity”);
ComponentName n3= new ComponentName(getPackageName(), “com.example.android_day16_intent.MainActivity”);
setComponent(n1);
这里写图片描述
Intent是什么
是一个简单的消息对象,它表示程序想做某事的“意图”,可以用来”激
活”Activity、Service或BroadCast Receiver。
比如想要从一个Activity启动另外一个Activity,就可以这么写:

Button btnToT2 = (Button)this.findViewById(R.id.btn_toT2);
btnToT2.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
Intent in = new Intent();
in.setClass(HelloWorldActivity.this, T2.class);
HelloWorldActivity.this.startActivity(in);
}
});

n Intent对象能包含下面六种数据:
1:Component name,组件名称:来处理Intent的组件类的全路径名称。可以通过
setComponent()、setClass()、setClassName()方法来进行设置,通过
getComponent()方法进行读取。
2:Action,动作:一个描述要做什么事情的字符串。在Intent类里面预定义了。
3:Data,数据:用来描述Action对应的具体的数据和数据的MIME Type,比如要打
电话,那么就是电话数据的uri,通常是“tel://”后面加上号码。如果是其他
的数据,通常是“content://”类型的uri。
相应的setData()方法仅仅用来设置URI,而setType()方法仅仅设置MIME
Type,setDataAndType()可以同时设置,另外可以通过相应的get方法获取值。
4:Category,类别:用来描述组件应该如何处理Intent的附加信息。在Intent类中
有Category具体的预定义。可以通过addCategory()、removeCategory()和
getCategories()来操作Category。
5:Extras,额外数据:传递给组件的附加数据,通常是key-value对。可以通过
putExtras()和getExtras()方法来操作数据
6:Flags,标记:各种各样的类别标记,用来描述如何装载Activity,以及装载后
如何处理这些Activity。

n Intent通常被分成两种:显式的和隐式的
1:显式的Intent:直接根据组件的名称来进行指派,通常用作应用内部的消息传递
机制,比如启动service或其他Activity等。
2:隐式的Intent:不用根据组件的名称来进行指派,通常用作启动其他应用的组
件。比如接收广播消息,Android系统需要寻找到最合适处理这个消息的应用,
通常会使用Intent Filter来实现。
n Intent Filter是什么
用来描述一个Activities、Services、BroadCast Receivers能够操作哪些
intent。它们都可以包含一到多个Intent Filter。
n Intent Filter能包含的数据通常只有三种:
action、data(包括URI和类型)、category。
n Intent Filter通常在AndroidManifest.xml文件里面配置使用
一个简要的示例如:





n发短信的示例
Uri uri = Uri.parse(“smsto:发送的号码”);
Intent in = new Intent(Intent.ACTION_SENDTO,uri);
in.putExtra(“sms_body”, “发个短信玩”);
Hello.this.startActivity(in);

n打电话的示例:
Uri uri = Uri.parse(“tel:发送的号码”);
Intent in = new Intent(Intent.ACTION_CALL,uri);
Hello.this.startActivity(in);

记得在AndroidManifest.xml文件中进行授权,

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值