使用Intent在活动间穿梭

一个应用中总会存在多个活动,通过这些活动的相互跳转,数据传递,逻辑处理,便可完成一个应用的功能。在各个活动的跳转时,会通过Intent(意图),Intent使Activity跳转大致可分为显示意图隐式意图.

1.使用显式 Intent

Intent有多个构造函数的重载,其中一个是Intent(Context packageContext ,Class<?>cls)。这个构造函数接收两个参数,第一个参数Context是要求提供一个启动活动的上下文,第二个参数需要指定一个目标活动。如下代码:

      Intent intent = new Intent(MainActivity.this,SecondActivity.class);

       startActivity(Intent);

活动本就是一个Context对象,所以第一个参数传入this,第二个参数传入SecondActivity为目标活动,然后通过startActivity()方法执行这个Intent。这种传入启动活动和目标活动的方式称为显示Intent,不要忘记在AndroidManifest.xml文件中添加Activity声明。

2.使用隐式 Intent

相比较与显示,隐式Intent则含蓄了很多,它并没有明确指出我们想要启动哪个活动,而是通过指定一系列更为抽象的actioncategory等信息,然后由系统去分析这个Intent,并帮我们找到合适的活动去启动。

什么叫做合适的活动呢,简单来说就是可以响应我们这个隐式Intent的活动,就目前来说,SecondActivity可以响应什么样的隐式Intent呢,其实它现在还什么都响应不了。需要我们手动的去设置。之前提到过要在配置文件中声明我们的活动,在活动的标签下配置<intent-filter>的内容,从字面理解标签的意思是<意图-筛选>。

   <activity  android:name=".SecondActivity">

       <intent-filter>

             <action name="com.hm.intenttestdemo.ACTION.START"/>

              <category name="android.intent.category.DEFAULT"/>

        </intent-filter>   

</activity>

只有某个活动能够同时匹配<action>和<category>时,才可以通过Intent来启动它。

   Intent intent = new Intent();

   intent.setAction("com.hm.intenttestdemo.ACTION.START");

   intent.addCategory(Intent.CATEGORY_DEFAULT);

   startActivity(intent);

初始化Intent,为intent设置Action,添加Category,此时系统会自动帮助我们找到合适的需要启动的活动,系统如何找到呢,这就回到了刚才我们在配置文件中设置的<intent-filter>标签的中的action和category了,如果同时满足,则该活动就是系统为我们找到的将要启动的最合适的活动了。其实每个活动在配置文件中声明时,都会默认设置category参数,默认的值都为Intent.Category_Default,所以该属性的设置通常使用时都省略设置了。

3.更多隐式Intent的用法

其实Intent的用法还有很多,设想一个应用需要访问一个网址,就拿百毒来说吧,我们可以在应用内做一个WebView活动专门负责上网,但是我们Android系统有自带强大的浏览器应用,那如何在使用其他应用时启动浏览器应用呢。通过下面的方法:

Intent intent =newIntent();

intent.setAction(Intent.ACTION_VIEW);

intent.setData(Uri.parse("www.baidu.com"));

startActivity(intent);

这里我们首先设置Intent的Action是Intent.Action_View,这个是Android内置的动作,其常量值为android.intent.action.VIEW.然后通过parse()方法,讲一个字符串转为Uri对象。再调用setData()方法将Uri传入。这样就可以访问系统的浏览器应用了。

回顾之前Intent的隐式意图的使用,在配置文件中<intent-filter>配置中也可以添加<data>标签,用于指定当前活动能够响应什么样的数据类型。

android:scheme 用于指定数据的协议部分,如上例中的http部分

android:host 用于指定数据的主机名部分,如上列中的www.baidu.com

android:port 用于指定数据的端口部分,一般紧随在主机名之后

android:path 用于指定主机名和端口之后的部分,如一段网址中跟在域名之后的内容

android:mimeType 用于指定可以处理的数据类型,允许指定通配符的方式进行指定。

只有指定了<data>标签中的内容和Intent中的携带的Data完全一致时,当前活动才能够响应Intent.但是通常在<intent-filter>的<data>中,都不会指定过多的内容,比如上面的例子,只需要指定android:scheme为http,就可以响应所有的http协议的Intent了。同样的如果你同时配置了android:host为www.baidu.con时,那Intent携带的data也只能为该Url地址才能响应活动。

当然,除了http协议外,我们还可以指定其他更多的协议,来调用系统的应用为我们服务,比如相机(Camera),电话(Tel),地理位置(Geo)等。

4.Intent传递数据(向下)

当我们通过Intent在各个活动跳转时,避免不了需要传递数据,在向目标活动传递数据时,不管是通过显示还是隐式的方式传递时,系统提供了很多方便的Api供我们使用。

 Intent intent = new Intent(Context context,XXActivity.class);

 intent.putExtra("IngeterNum",12);

 intent.putExtra("DoubleNum",10.123);

 intent.putExtra("BooleanFlag",true);

 intent.putExtra("StringStr","haha");

 startActivity(intent);

当然在目标活动页,就是需要接受参数的活动页我们通过:

  Intent intent = getIntent();

  int intNum = intent.getIntExtra("IngeterNum",10);  

  String str = intent.getStringExtra("StringStr");

我们可以发现在putExtra()方法中传入的Key要与目标活动页使用getXXExtra()方法接收参数时传入的key要完全相同,同时有的该方法需要你传入一个默认值,通常基本的参数类型只需要设置就可以使用了。

基本类型使用很简单,如果我们需要传递对象怎么办?其实也只是比基本类型稍微复杂一点,当我们创建一个对象时,会接触到一个对象可序列化的概念,通过类实现Serializable接口或者Parcelable。

4.1通过实现Serializable接口

实现Serializable的Person对象

传递数据

  Person p =newPerson();

  p.setAge(25);

  p.setName("张三");

  intent.putExtra("Person_Key",p);

  startActivity(intent);

接收数据

Person person = (Person)getIntent().getSerializableExtra("Person_Key");

同样传递数据和接收数据时的Key要统一。

4.2通过转为Json字符串传递

  将对象类型转为字符串类型,也是数据传递的一种方式

传递数据

  Person p =newPerson();

  p.setAge(25);

   p.setName("张三");

   intent.putExtra("Person_Json_key",new Gson().toJson(p));

   startActivity(intent);

接收数据

String personJson = getIntent().getStringExtra("Person_Json_key");

Person p = newGson().fromJson(personJson,Person.class);

该方法主要使用Gson对象的方法,先将对象转为String,再将String在目标活动界面接收后转为对象。

4.3通过实现Parcelable接口

实现Parcelable接口需要实现两个方法

describeContents方法。 内容接口描述,默认返回0就可以。

writeToParcel方法。 将传递的数据打包到Parcelable容器中。

除了要实现这两个方法还必须要创建一个Parcelable.Creator接口的实例,用于读取Parcel容器中的数据


实现Parcelable接口的Person实例


传递数据

Person p =newPerson();

p.setAge(25);

p.setName("张三");

intent.putExtra("Person_Json_key",new Gson().toJson(p));

startActivity(intent);

接收数据

Person person = (Person)getIntent().getSerializableExtra("Person_Key");

同样传递数据和接收数据时的Key要统一。


简化Parcel操作

如果你使用android Studio 可以通过安装android-parce-intellij-plugin插件,或者自己配置模板进行操作。

5.Intent传递数据(向上)

Intent既然可以向下一个活动传递数据,自然也可以向上一个活动传递数据,当然返回上一个活动只需要按一下设备的返回按钮便会返回到上一个活动。但是如何向上一个活动传递数据呢?其实startActivity()方法是开启一个新的活动,startActivityForResult()方法也是开启一个新活动的方法,当然该方法有两个参数,第一个参数毫无疑问是intent,第二参数是一个整形参数的请求码。

   Intent intent = new Intent(context,OtherActivity.class);

   startActivityForResult(intent,1);

我们来到刚才启动的OtherActivity活动页面,通过出发一个Button的点击事件来返回到上一个活动页。

   ((Button)findViewById(R.id.id_button)).setOnClickListener(new View.OnClickListener(){

                  public void OnClick(View view){

                         Intent intent = new Intent();

                         intent.putExra("data_return","Hello FirstActivity");

                        setResult(RESULT.OK,intent);

                        finish();

                     }

});

在button的点击事件中,我们先创建了Intent对象,通过putExtra()方法为Intent添加需要传递的参数,调用活动的setResult()方法,然后finish()掉本活动。注意setResult()方法,传递了两个参数,一个是RESULT.OK,这个是系统的整形常量,与它相似的还有一个是RESULT.CANCELED,这两个值代表的是向上返回的处理结果,intent中携带者需要向上传递的数据.由于我们启动下一个活动使用的是startActivityForResult()方法,活动就会调用onActivityResult()方法,因此我们需要在FirstActivity中重写这个方法:

 @Override

 protected void onActivityResult(int requestCode, int resultCode,Intent data) {

    switch(requestCode) {

           case1:

           if(resultCode ==RESULT_OK) {

            String returnData = data.getStringExtra("data_return");

         Log.d("FirstActivity",returnData);

         }

        break;

}

onActivityResult()方法有三个参数,第一个参数requestCode,即我们请求活动跳转时传递的请求码,第二个参数时resultCode,即我们在返回数据时传入的处理结果,第三个参数时Intent(data),即返回携带者的Intent。因为可能会有多个地方在跳转到其他活动时调用startActivityForResult方法传入不同的requestCode,在返回上一个页面时调用setResult方法时,传入不同的处理结果码,所以我们在回调onActivityResult方法时需要通过盘点请求码(requestCode)和返回码(resultCode),来处理不同的逻辑。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,743评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,296评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,285评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,485评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,581评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,821评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,960评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,719评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,186评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,516评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,650评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,936评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,757评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,991评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,370评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,527评论 2 349

推荐阅读更多精彩内容