Android之Intent详解

1、Intent是一个将要执行的动作的抽象描述,一般是用来协助完成各个组件之间的通讯。Intent负责对应用中一次操作的动作及动作涉及的数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将Intent传递给调用的组件,并完成对组件的调用。可以说,Intent起着媒介的作用,专门提供提供组件相互调用的相关信息,实现调用者和被调用者之间的控制。

 

2、Intent的构成

1)Action:用来指明要实施的动作是什么。如ACTION_VIEW, ACTION_EDIT等

2)Data:具体的数据,一般由Uri变量来表示

3)Category:指定将要执行的这个action的其它一些额外的信息。例如 LAUNCHER_CATEGORY 表示Intent 的接受者应该在Launcher中作为顶级应用出现;而ALTERNATIVE_CATEGORY表示当前的Intent是一系列的可选动作中的一个,这些动作可以在同一块数据上执行。

4)Type:显示指定Intent的数据类型。一般Intent的数据类型能够根据数据本身进行判定,但是通过设置这个属性,可以强制采用显式指定的类型而不再进行推导。

5)Component:指定Intent的目标组件的类名称。通常Android会根据Intent中包含的其它属性的信息,比如action、data/type、category进行查找,最终找到一个与之匹配的目标组件。但是,如果 component这个属性有指定的话,将直接使用它指定的组件,而不再执行上述查找过程。指定了这个属性以后,Intent的其它所有属性都是可选的。

6)Extra:附加信息,是其它所有附加信息的集合。使用extras可以为组件提供扩展信息。比如,如果要执行“发送电子邮件”这个动作,可以将电子邮件的标题、正文等保存在extras里,传给电子邮件发送组件。

 

3、Intent中data数据的Uri结构

android采用指向数据的一个URI来表示数需要操作的数据。

URI主要分三部分:scheme、authority和path,其中authority可分为host和port。格式:scheme://host:port/path

实例如下:

content://com.example.project:200/folder/subfolder/etc
\---------/  \---------------------------/ \---/ \--------------------------/
scheme                 host               port        path
                \--------------------------------/
                          authority   

4、Intent解析

应用程序的组件为了告诉Android自己能响应、处理哪些隐式Intent请求,可以声明一个甚至多个Intent Filter。每个Intent Filter描述该组件所能响应Intent请求的能力——组件希望接收什么类型的请求行为,什么类型的请求数据。比如之前请求网页浏览器这个例子中,网页浏览器程序的Intent Filter就应该声明它所希望接收的Intent Action是WEB_SEARCH_ACTION,以及与之相关的请求数据是网页地址URI格式。如何为组件声明自己的Intent Filter? 常见的方法是在AndroidManifest.xml文件中用属性< Intent-Filter>描述组件的Intent Filter。

<activity android:name="com.example.learn.MainActivity" android:label="@string/app_name" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

 

5、android解析Intent的流程

在应用中具体分成两种Intent:直接Intent 间接Intent

直接intent就是指定了component属性的intent(调用setComponent(componentName))。通过指定具体的组件类,通知应用启动对应的组件;
间接intent是没有指定component属性的intent,这些intent需要包含足够的信息,这样系统才能确定启动对应的组件;

对于直接Intent,Android不需要去做解析,因为目标组件已经很明确,Android需要解析的是那些间接Intent,通过解析,将Intent映射给可以处理此Intent的Activity、Broadcaset receiver或Service。Intent解析机制主要是通过查找已注册在AndroidManifest.xml中的所有IntentFilter及其中定义的Intent,最终找到匹配的Intent。在这个解析过程中,Android是通过Intent的action、type、category这三个属性来进行判断的,判断方法如下:

●  如果intent指明了action,则目标组件的intentFilter的action列表就必须包含有这个action,否则不能匹配;
●  如果Intent没有提供type,系统将从data中得到数据类型。和action一样,目标组件的数据类型列表中必须包含Intent的数据类型,否则不能匹配。
● 如果Intent中的数据不是content: 类型的URI,而且Intent也没有明确指定它的type,将根据Intent中数据的scheme(比如 http: 或者mailto:)进行匹配。同上,Intent 的scheme必须出现在目标组件的scheme列表中。
● 如果Intent指定了一个或多个category,这些类别必须全部出现在组建的类别列表中。比如Intent中包含了两个类别:LAUNCHER_CATEGORY 和 ALTERNATIVE_CATEG
ORY,解析得到的目标组件必须至少包含这两个类别。


6、catetory的类别总结:

android.intent.category.ALTERNATIVE:ALTERNATIVE 种类指定,在某种数据类型的项目上可以替代默认执行的动作。例如,一个联系人的默认动作时浏览它,替代的可能是去编辑或删除它。   

android.intent.category.BROWSABLE:指定在浏览器中的动作。当 Intent 在浏览器中被引发,都会被指定成 BROWSABLE 种类。  

android.intent.category.DEFAULT :设置这个种类来让组件成为 Intent Filter 中定义的 data 的默认动作。这对使用显式 Intent 启动的 Activity 来说也是必要的。

android.intent.category.DEVELOPMENT_PREFERENCE   

android.intent.category.EMBED   

android.intent.category.HOME:HOME Activity 是设备启动(登陆屏幕)时显示的第一个 Activity 。通过指定 Intent Filter 为 HOME 种类而不指定动作的话,你正在将其设为本地 home 画面的替代。      

android.intent.category.INFO

android.intent.category.LAUNCHER:使用这个种类来让一个 Activity 作为应用程序的启动项。   

android.intent.category.MONKEY   

android.intent.category.OPENABLE   

android.intent.category.PREFERENCE    

android.intent.category.SELECTED_ALTERNATIVE:与 ALTERNATIVE 类似,但 ALTERNATIVE 总是使用下面所述的 Intent 解析来指向单一的动作。SELECTED_ALTERNATIVE在需要一个可能性列表时使用。   

android.intent.category.TAB

 

7、Intent有两种基本用法:一种是显示的Intent,即在构造intent对象时就指定接收者,这种方式与普通的函数调用类似。另一种是隐式的intent,即intent的发送者在构造intent对象时,但是并不关心接收者,有利于降低发送者和接收者之间的耦合。

 

8、bundle

android使用Intent.putSerializable()进行数据传递,或者使用Bundle进行数据传递。实质上都是进行的Serializable数据的操作,都是传递源数据的一份拷贝。

public void onCreate(Bundle savedInstanceState) {  
    super.onCreate(savedInstanceState);  
    setContentView(R.layout.main);  
          
    // 定义一个Bundle按键   
     Button gotoBundle = (Button)findViewById(R.id.btnBundle);  
    // 设置监听事件   
     gotoBundle.setOnClickListener(new View.OnClickListener(){  
  
    @Override  
    public void onClick(View v) {  
       Intent intent = new Intent();  
       intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
       intent.setClass(getApplicationContext(), GetBundleActivity.class);  
                  
       DataBean temp  = new DataBean();  
       temp.setID(1);  
       temp.setName("张三");  
       temp.setAddress("xx市xx路xx号");  
       temp.setMoblie("159xxxxxxxx");  
                  
       Log.i("AndroidbundleActivity", "新建时候的地址" + temp);     
                  
       Bundle bundle = new Bundle();  
       bundle.putSerializable("UserInfo", temp);  
                  
       // 设置intent   
       intent.putExtras(bundle);  
                  
       // 发送Activity   
       getApplicationContext().startActivity(intent);  
    }              
  });  
}  
public void onCreate(Bundle savedInstanceState) {  
    // 初始化BundleActivity   
    super.onCreate(savedInstanceState);  
    setContentView(R.layout.bundle);  
          
    // 获取意图   
    Intent intent = getIntent();  
    Bundle bundle = intent.getExtras();  
          
    // 获取对象   
    DataBean temp = (DataBean) bundle.get("UserInfo");  
    Log.i("GetBundleActivity", "收到的地址" + temp);  
}  

 

9、intent实例

1)无参数activity跳转

Intent intent = new Intent(Activity.Main.this, Activity2.class);  
startActivity(intent); 

2)向下一个activity传递数据(使用bundle和putExtras)

Intent intent = new Intent(Activity.Main.this, Activity2.class);  
Bundle bundle=new Bundle();  
bundle.putString("name", "This is from MainActivity!");  
intent.putExtras(bundle);  
//startActivity(intent);  
startActivityForResult(intent,REQUEST_CODE);  
Bundle bundle=getIntent().getExtras();  
String name=bundle.getString("name");  

3)向上一个Activity返回结果(使用setResult,针对 startActivityForResult(it,REQUEST_CODE)启动的Activity)

Intent intent=getIntent();  
Bundle bundle=new Bundle();  
bundle.putString("name", "This is from Activity2!");  
intent.putExtras(bundle);  
setResult(RESULT_OK, intent);  


注解:

startActivityForResult(Intent intent, Int requestCode):requestCode >=0就好,随便用于在onActivityResult()区别哪个子模块回传的数据,如果还有C.java ,D甚至E子模块的话,每个区分开不同的requestCode就好。
setResut(int resultCode, Intent intent):resultCode 如果B子模块可能有几种不同的结果返回,可以用这个参数予以识别区分。这里还有个特殊的 RESULT_OK 值,没有特殊情况用它就好了。intent 传回给A的onActivityResult()
onActivityResult(int requestCode, int resultCode, Intent intent):如果不对requestCode和resultCode 加以识别区分的话,只要有其他activity setResult到了A  
onActivityResult()会无差别处理。

4)回调上一个Activity的结果处理函数(onActivityResult)
@Override      
protected void onActivityResult(int requestCode, int resultCode, Intent data) {          
    // TODO Auto-generated method stub           
    super.onActivityResult(requestCode, resultCode, data);          
    if (requestCode==REQUEST_CODE){              
       if(resultCode==RESULT_CANCELED)                    
           setTitle("cancle");              
       else if (resultCode==RESULT_OK) {                   
           String temp=null;                   
           Bundle bundle=data.getExtras();                   
           if(bundle!=null)   
              temp=bundle.getString("name");                   
           setTitle(temp);              
       }          
     }      
}  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值