Android-活动(Activity)Intent
稍微正常点的应用都应该不只有一个活动,通常都是有成打的活动,然后通过各种事件进行跳转。连接起各种活动的桥梁,就是所谓的Intent。
什么是Intent?
Intent是Android用来连接各个组件并且将组件进行j解耦的重要组件,比如指明当前组件的意图,或者在组件之间传递数据。
Intent相当于一个媒婆,为两个组件牵线搭桥,并且为他们之间的信息交换提供了渠道。比如,有一个人(Activity)想找个白富美当老婆,他把这个“意图”写在了脸上,然后让媒婆(Intent)去找找看,有没有这么个人是符合要求的。媒婆找了找,还真有一个符合条件的人,然后就把这俩人介绍到一起,并且为对方提供他们想了解的数据。
Intent也分为两种:显式Intent(点名道姓)和隐式Intent(条件筛选)。我们一个一个说。
显式Intent
首先上代码:
因为我们要实现Activity的跳转,所以我们要建立两个活动才行:
1 public class FirstActivity extends AppCompatActivity //第一个活动 2 { 3 4 @Override 5 protected void onCreate(Bundle savedInstanceState) 6 { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.activity_main); 9 Button button1 = (Button) findViewById(R.id.button_1); 10 button1.setOnClickListener(new View.OnClickListener() 11 { 12 @Override 13 public void onClick(View v) 14 { 15 Intent intent = new Intent(FirstActivity.this, SecondActivity.class); 16 startActivity(intent); 17 } 18 }); 19 } 20 }
1 public class SecondActivity extends AppCompatActivity //第二个活动 2 { 3 4 @Override 5 protected void onCreate(Bundle savedInstanceState) 6 { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.activity_second); 9 } 10 }
第一个活动对应的布局文件:
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android:layout_width="match_parent" 3 android:layout_height="match_parent"> 4 5 <Button 6 android:id="@+id/button_1" 7 android:layout_width="wrap_content" 8 android:layout_height="wrap_content" 9 android:text="This is Button 1" /> 10 </LinearLayout>
第二个布局文件没写什么,就不放上来了。
我们分析下代码:
FirstActivity在Button的点击事件中定义了一个Intent(媒婆),这个Intent有很多构造函数的重载,我们这里使用的是
Intent(Context packageContext,Class<?> cls);
这里我们要传入两个参数:第一个是这个启动活动的上下文(上下文的解释看上一篇),第二个是我们这个Intent的“意图”,也就是我们这个Intent想跳转到哪里。但是我们要注意,第一个传入的是对象(.this),第二个是.class,传入类文件之后,虚拟机会自动装载类文件。
接下来,我们的Intent已经准备妥当,我们还需要去启动Intent。使用startActivity(Intent intent),传入我们的Intent就可以发动“媒婆”,启动目标活动了。
隐式Intent
显示Intent好比是指明了要志玲做老婆,点名道姓,意图明显。而隐式Intent,是规定了条件,只有符合条件的才能被我接纳。
要想能匹配得上,有两部分要完全相同:action和category。
废话不多说,上代码,首先是AndroidMainifest.xml(只贴出修改部分)
1 <activity android:name=".SecondActivity"> 2 <intent-filter> 3 <action android:name=".ACTION_START" /> 4 <category android:name="android.intent.category.DEFAULT" /> 5 </intent-filter> 6 </activity>
我们修改了SecondActivity的标签,为它加入了action和catagory标签。action标签说明了我们这个活动可以响应哪个action。action表明了我们这个活动可以执行的动作,可以使用系统提供的(比如拨号ACTION_CALL),也可以自己定义。这里我们是自己定义的;catagory包含了更加细节的一些信息。
然后我们修改FirstActivity.java的代码
1 public class FirstActivity extends AppCompatActivity 2 { 3 @Override 4 protected void onCreate(Bundle savedInstanceState) 5 { 6 super.onCreate(savedInstanceState); 7 setContentView(R.layout.activity_main); 8 Button button1 = (Button) findViewById(R.id.button_1); 9 button1.setOnClickListener(new View.OnClickListener() 10 { 11 @Override 12 public void onClick(View v) 13 { 14 Intent intent = new Intent(".ACTION_START"); 15 startActivity(intent); 16 } 17 }); 18 } 19 }
我们修改了Intent的构造函数,直接传入了action的字符串,表明我们想启动能响应.ACTION_START这个action的活动。但是,我们在这里并没有出现于category的相关声明,是怎么回事呢?
因为我们给SecondActivity传入的是"android.intent.category.DEFAULT"这个参数,这是一个默认的catgory,在我们startActivity时会自动调用这个参数到我们的intent中。
我们启动程序,效果与刚才的是一样的。
当然,我们也可以指定多个category,但是只能有一个action。
1 intent.addCategory(".MY_CATEGORY1"); 2 intent.addCategory(".MY_CATEGORY2");
这样就可以为我们的intent添加category了。
但是我们的所有活动里面必须有一个是能响应你这个intent的,否则程序会崩溃。
隐式Intent的更多用法
我们在平时使用别人家的app时一定有过这样的体验:点击一个链接,系统会提示你选择哪一个浏览器打开网页。这些动作都是通过Intent来完成的。接下来我们看看Intent还有什么新玩法。
修改代码如下:
1 @Override 2 public void onClick(View v) 3 { 4 Intent intent = new Intent(Intent.ACTION_VIEW); 5 intent.setData(Uri.parse("http://www.baidu.com")); 6 startActivity(intent); 7 }
我们这里传入的是"ACTION_VIEW"这个action,这是一个系统内置的action。然后我们调用intent的setData方法。这个方法是用来指定我们当前Intent操作的数据,它的参数是一个Uri对象。所以我们里面使用Uri.parse来将一个网址解析成为了一个Uri对象(parse,分析的意思)。然后我们重新运行程序:
可以看到我们的程序成功响应了我们的请求,打开了我们指定的网页。
那我们的程序能不能响应打开网页的请求呢?我们只要在相应的activity标签中去添加属性就可以了。
修改AndroidManifest.xml如下:
1 <activity android:name=".SecondActivity"> 2 <intent-filter tools:ignore="AppLinkUrlError"> 3 <action android:name="android.intent.action.VIEW" /> 4 <category android:name="android.intent.category.DEFAULT" /> 5 <data android:scheme="http" /> 6 </intent-filter> 7 </activity>
我们修改了SecondActivity的属性,让他能响应所有http协议的网址。并且修改了action为系统内置的action,它能响应Intent.ACTION_VIEW,也就是我们刚才传入的那个值。
我们还能指定的data有:
android:scheme 指定数据的协议,如http;
android:host 指定数据的主机名,如www.baidu.com
android:port 指定端口,比如:8080,:80
还有很多,不常用的就不写在这里了。
我们点击FirstActivity的按钮之后:
可以看到,我们的IntentDemo能够响应网页的请求了,就是因为我们在SecondActivity中添加了一个“可以响应http协议”的属性。
除了网页,我们还可以让其响应拨号事件:
1 Intent intent = new Intent(Intent.ACTION_DIAL); 2 intent.setData(Uri.parse("tel:10010"));
使用Intent传递数据
传递数据给下一个活动
到目前为止,我们还只是使用Inten来跳转活动。但是我们如果有需求,让活动在跳转的时候传递数据呢?
很简单,Intent是一个桥梁,你把你想传的放在桥上,然后让另外一个人过来取不就行了吗。Intent为我们提供了一个各式各样的篮子,我们根据我们的需要,将数据放在篮子里就行了。
上代码!
1 @Override 2 public void onClick(View v) 3 { 4 String data = "马什么梅?"; 5 Intent intent = new Intent(FirstActivity.this, SecondActivity.class); 6 intent.putExtra("my_data", data); 7 startActivity(intent); 8 }
我们定义了一个字符串,用来作为传递的数据。(马冬什么?)然后我们使用的是显式Intent,并使用putExtra(String name,DataType value)方法来传值的(DataType代表很多数据类型)。
第一个参数,是这个数据的“键”。你可以理解为关键字,也可以简单的理解这个数据的名字。你把数据放我这个大篮子里面了,不得标示一下这个数据的身份吗,否则到时候用找谁拿去啊。
第二个参数就是我们的数据了。
然后我们在SecondActivity中相应的去接收数据:
1 @Override 2 protected void onCreate(Bundle savedInstanceState) 3 { 4 super.onCreate(savedInstanceState); 5 setContentView(R.layout.activity_second); 6 Intent intent = getIntent(); 7 String data = intent.getStringExtra("my_data"); 8 Toast.makeText(SecondActivity.this, data, Toast.LENGTH_SHORT).show(); 9 }
我们定义了一个Intent,并用getIntent()方法来获取到用来启动这个activity的Intent。然后使用getStringExtra(String name)来获取我们存在“篮子”里面的字符串,参数当然就是我们刚才设置的数据的名字(键)。为了展示是否成功,我就简单的去Toast了一下。
可以看到,我们成功返回了数据。我们这里传的是字符串,要是Boolean就是getExtraBoolean,其他的以此类推,传的什么类型就接什么。
返回数据给上一个活动
我们传递数据给下一个活动是使用的Intent来暂存的,但是我们要是想直接返回上一个活动只需要按下返回键就可以了,并没有什么Intent参与其中。这时候我们的思路就要转换一下了。你不主动给我?那好,我直接在启动你的时候向你伸手要总行了吧!
修改FirstActivity的代码如下:
1 @Override 2 public void onClick(View v) 3 { 4 Intent intent = new Intent(FirstActivity.this, SecondActivity.class); 5 startActivityForResult(intent,1); 6 }
既然是张嘴要,就给在启动的时候说明白了。使用startActivityForResult(Intent intent,int requestCode),第一个就是我们的Intent,第二个是请求码。要是有很多数据返回来的话,我们要对他们进行区分,这就是请求码的用意。
接下来就是SecondActivity:
1 @Override 2 public void onClick(View v) 3 { 4 Intent intent = new Intent(SecondActivity.this,FirstActivity.class); 5 intent.putExtra("data_return", "什么冬梅?"); 6 setResult(RESULT_OK, intent);7 }
我们还是构建了一个Intent来跳转到上一个活动。然后放一个字符串,并使用setResult(int resultCode,Intent data)来向上一个活动传值。第一个是结果值,一般使用RESULT_OK和RESULT_CANCELED两个值,用来告诉上一个活动返回数据的处理结果。第二个就是我们的intent了。
我们既然要向上一个活动返回数据,就得有相应的措施来处理返回数据。
添加FirstActivity的代码:
1 @Override 2 protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) 3 { 4 switch (requestCode) 5 { 6 case 1: 7 if (resultCode == RESULT_OK) 8 Toast.makeText(FirstActivity.this, data.getStringExtra("data_return"), Toast.LENGTH_SHORT).show(); 9 break; 10 default: 11 } 12 }
我们重写了FirstActivity的onActivityResult方法。这个方法接收三个参数,具体意义就不讲了,都能看明白。
因为数据会有很多,所以我们第一件事就是去判断数据来源,也就是我们的requestCode。因为如果有多个时间指向同一activity的话我们就必须分清数据从哪里来。然后我们还需要去检查结果码,看看是不是成功了。
好了,这就是Intent的内容,对于我们初学者来说,这些内容很够了。
菜鸟一个,多多指教!