Intent使用 | 青训营笔记

49 阅读4分钟

这是我参与「第四届青训营 」笔记创作活动的第2天 今天笔记的内容是intent详解

Intent的概念与使用

关于Intent,目前只用在启动activity上,通常启动一个activity时需要传递一个intent参数给指定的activity,同时也可以在这个Intent中夹带一些参数进行传递。

用显示Intent启动Activity

显示intent就是指定了要启动的activity的类的intent,这种intent通常是用在app内activity之间的交互。接下来就来在一个项目里注册两个activity来看一看如何用intent启动。

如果不直接新建activity,就要新建一个java类,并令它继承Activity类,还要在res文件夹中新建layout文件定义其ui。之后在java文件中实现Activity的各个方法,通常在onCreate方法中进行layout与activity的绑定:

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.myaty);
    }

之后为了使用这个activity中,我们还需要在AndroidManifest文件中进行注册,注意activity的name会与manifest的package组合起来作为Activity类的名称,所以在这里注册时可以使用简写,也可以在name中写全包名.类名

<manifest ...
    package="com.example.study4intent">

    <application ...> 
        <activity android:name=".MyAty">
<!--           name added to package as the name of an Activity object-->
<!--            use com.example.study4intent.MyAty instead-->
            ...
        </activity>
    </application>
</manifest>

到这里,我们就已经新建了一个activity,并且可以绑定它对应的java和res文件了。如果直接在AS中新建activity的话,ide会自动帮我们完成这些配置工作。

到这里,我们就可以试着用显示intent启动activity了,这里选择用一个按钮来触发新activity的启动:

findViewById(R.id.button).setOnClickListener(
    new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent =
                new Intent(MainActivity.this, MyAty.class);
            startActivity(intent);
        }
    }
);

java允许传new出来的参数,而new抽象类需要实现抽象方法,这种嵌套方式写出来的代码非常紧凑,不过通常我们会把findViewById的结果声明为private变量保存下来方便以后调用。

查看Intent构造器可知Intent可以用一个Context类型对象和一个class泛型来构造,这就是我们的显示Intent要传递的包名和类名。

public Intent(Context packageContext, Class<?> cls)

隐式Intent

Intent除了用显式指定的包名和类名构造之外,也可以先通过一个标记构造,之后再寻找标记对应的类。最常见的方法是使用action,也就是一个字符串。如果用action构造了一个intent,那么就可以直接用这个字符串搜索到注册了这个action的类。(小疑惑,如果有两个一样的action会怎样呢?)

注册action

在androidmanifest文件中,activity下加入intent-fliter标签:

    <intent-filter>
        <category android:name="android.intent.category.DEFAULT"/>
        <action android:name="qaq"/>
    </intent-filter>

注意,新版Android可能会报错,要求指定activity是否exported,直接用快速修复功能设置为true即可。下文会讲到。

category的name暂时选择default就可以,而action的name则要注册为对应的字符串,标准的action格式是<package_name>.action.start.<class_name>,不过这个格式实在过于复杂,我们也可以把action的名字放在要启动的类中,作为一个常量

public class MyAty extends Activity {
    public static final String ACTION = "qaq";
    ...
}

这样在使用Intent时,就不需要直接输入长长的字符串,使用MyAty.ACTION就可以了

用隐式Intent启动同一个app内的另一个Activity

基本的方法和之前都是相同的,区别就是构造intent时调用了另一种构造器:

findViewById(R.id.button).setOnClickListener(
    new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Intent intent =
-                new Intent(MainActivity.this, MyAty.class);
+                new Intent("qaq");
            startActivity(intent);
        }
    }
);
public Intent(String action)

当然,隐式Intent最主要的作用并不是用来启动同一个应用内的activity,因为此时我们是可以直接获得这个activity的类的定义的。而在跨应用通讯时,隐式Intent就有用处了。

用Intent跨应用启动activity

还记得之前AS可能会要求我们添加的exported属性吗:

        <activity android:name=".MyAty"
+            android:exported="false">
            <intent-filter>
                <category android:name="android.intent.category.DEFAULT"/>
                <action android:name="qaq"/>
            </intent-filter>
        </activity>

这是安卓权限管理引入的机制:只有设置为exported的activity对其他应用才是可见的,现在我们可以把它改为true,然后在project中新建一个package(app),并且在另一个app中启动这个app的activity

findViewById(R.id.btn_start_myaty).setOnClickListener(
        new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                startActivity(new Intent("qaq"));
                } catch (Exception e) {
                    Toast.makeText(MainActivity.this, "无法启动MyAty",Toast.LENGTH_SHORT).show();
                }
            }
        }
);

这里使用了try结构来捕获可能的异常,如果前面没有正确的设置exported的话,就可能导致异常的出现。捕获到异常之后,用Toast组件打印一条提示信息。