股票场内基金交易,没时间盯盘?
引言
Intent,意图,主要解决Android各项组件之间的通讯问题。Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将 Intent传递给调用的组件,并完成组件的调用。因此,Intent在这里起着一个媒体中介的作用,专门提供组件互相调用的相关信息,实现调用者与被调用者之间的解耦。
而Intent又分为两种,显式Intent(Explicit intent) 和 隐式Intent(Implicit intent)。这篇文章主要就来介绍一下这两种Intent。
启动模式
Intent作为我们Android程序员经常要面对的一个组件,最常用的就是去启动一个Activity了,所以在这里我们就先拓展一下Activity的四种启动模式。
(1)standard:每次激活Activity时(startActivity),都创建Activity实例,并放入任务栈;这个是系统默认的启动模式;
(2)singleTask:如果要激活的那个Activity在任务栈中存在该实例,则不需要创建,只需要把此Activity放入栈顶,并把该Activity以上的Activity实例都pop(弹出销毁);这个模式可以用来退出整个应用。将主Activity设为SingTask模式,然后在要退出的Activity中转到主Activity,然后重写主Activity的onNewIntent函数,并在函数中加上一句finish。(因为Activity不创建,所以不会进入onCreate函数,只会进入onNewIntent函数)。
(3)singleInstance:如果应用1的任务栈中创建了MainActivity实例,如果应用2也要激活MainActivity,则不需要创建,两应用共享该Activity实例;
此启动模式和我们使用的浏览器工作原理类似,我们都知道在多个程序中访问浏览器时,如果当前浏览器没有打开,则打开浏览器,否则会在当前打开的浏览器中访问。此模式会节省大量的系统资源,因为他能保证要请求的Activity对象在当前的栈中只存在一个。
(4)singleTop:如果在任务的栈顶正好存在该Activity的实例, 就重用该实例,否者就会创建新的实例并放入栈顶(即使栈中已经存在该Activity实例,只要不在栈顶,都会创建实例)。
在每次使用新的Activity时会自动检测栈顶的当前Activity是否是需要引用的Activity,如果是则直接引用此Activity,而不会创建新的Activity;当它不需要创建新的Activity对象时,它会调用onNewIntent()方法。
任务栈:每个应用都有至少一个任务栈,是用来存放Activity的,功能类似于函数调用的栈,先后顺序代表了Activity的出现顺序;比如Activity1–>Activity2–>Activity3,则任务栈为:
好,下面我们进入正文。
显式Intent
显式,顾名思义,就是明显指出了目的组件,有以下三种启动方式:
1.构造方法传入目标组件,这也是我们最常用的方式
1 2 3 |
Intent intent = new Intent(this, IntentDemo2Activity); startActivity(intent); |
2.setComponent方法
1 2 3 4 5 6 7 8 |
ComponentName componentName = new ComponentName(this,IntentDemo2Activity.class); //或者 //ComponentName componentName = new ComponentName(this,"com.jyx.demo.myapplication.IntentDemo2Activity"); Intent intent = new Intent(); intent.setComponent(componentName); startActivity(intent); |
3.setClass/setClassName方法
1 2 3 4 5 6 7 8 |
Intent intent = new Intent(); intent.setClass(this, IntentDemo2Activity.class); // 或者intent.setClassName(this, "com.jyx.demo.myapplication.IntentDemo2Activity"); // 或者intent.setClassName(this.getPackageName(), "com.jyx.demo.myapplication.IntentDemo2Activity"); startActivity(intent); |
显式Intent通过设置目标Component来调用需要前往的组件,可以直接确定一个目标组件,意图明确,所以称之为显式Intent。设置这个类的方式可以是Class对象(如IntentDemo2Activity.class),也可以是包名加类名的字符串(如”com.jyx.demo.myapplication.IntentDemo2Activity”)。这个很好理解,在应用程序内部跳转界面常用这种方式。
隐式Intent
隐式Intent,就是并不直接指明目标组件,而是通过设置Action、Data、Categroy,然后让系统来筛选出来符合条件得组件,筛选是根据所有的来筛选。例如:
AndroidManifest.xml文件中,首先被调用的Activity要有一个带有并且包含的Activity,设定它能处理的Intent,并且category设为”android.intent.category.DEFAULT”。action的name是一个字符串,可以自定义,例如我在这里设成”testIntent”
1 2 3 4 5 6 7 |
<activity android:name=".IntentDemo2Activity"> <intent-filter> <action android:name="testIntent"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity> |
然后我们就可以在IntentDemoActivity中这么写来调用IntentDemo2Activity:
1.setAction方法
1 2 3 4 |
Intent intent = new Intent(); intent.setAction("testIntent"); startActivity(intent); |
2.直接在构造方法里设置
1 2 3 |
Intent intent = new Intent("testIntent"); startActivity(intent); |
通过在AndroidManifest.xml里设置Action,来表明自己的意图,其他Activity就可以通过Intent找到这个Activity并启动。除了自己可以设置Action,Android还为我们提供了许多系统常用界面的Action,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
// 调用浏览器 Uri webViewUri = Uri.parse("http://blog.qiji.tech/archives/author/jyx5323"); Intent intent = new Intent(Intent.ACTION_VIEW, webViewUri); // 调用地图 Uri mapUri = Uri.parse("geo:100,100"); Intent intent = new Intent(Intent.ACTION_VIEW, mapUri); // 播放mp3 Uri playUri = Uri.parse("file:///sdcard/test.mp3"); Intent intent = new Intent(Intent.ACTION_VIEW, playUri); intent.setDataAndType(playUri, "audio/mp3"); // 调用拨打电话 Uri dialUri = Uri.parse("tel:10086"); Intent intent = new Intent(Intent.ACTION_DIAL, dialUri); // 直接拨打电话,需要加上权限<uses-permission id="android.permission.CALL_PHONE" /> Uri callUri = Uri.parse("tel:10086"); Intent intent = new Intent(Intent.ACTION_CALL, callUri); // 调用发邮件(这里要事先配置好的系统Email,否则是调不出发邮件界面的) Uri emailUri = Uri.parse("mailto:zuolongsnail@163.com"); Intent intent = new Intent(Intent.ACTION_SENDTO, emailUri); // 直接发邮件 Intent intent = new Intent(Intent.ACTION_SEND); String[] tos = { "zuolongsnail@gmail.com" }; String[] ccs = { "zuolongsnail@163.com" }; intent.putExtra(Intent.EXTRA_EMAIL, tos); intent.putExtra(Intent.EXTRA_CC, ccs); intent.putExtra(Intent.EXTRA_TEXT, "the email text"); intent.putExtra(Intent.EXTRA_SUBJECT, "subject"); intent.setType("text/plain"); Intent.createChooser(intent, "Choose Email Client"); // 发短信 Intent intent = new Intent(Intent.ACTION_VIEW); intent.putExtra("sms_body", "the sms text"); intent.setType("vnd.android-dir/mms-sms"); // 直接发短信 Uri smsToUri = Uri.parse("smsto:10086"); Intent intent = new Intent(Intent.ACTION_SENDTO, smsToUri); intent.putExtra("sms_body", "the sms text"); // 发彩信 Uri mmsUri = Uri.parse("content://media/external/images/media/23"); Intent intent = new Intent(Intent.ACTION_SEND); intent.putExtra("sms_body", "the sms text"); intent.putExtra(Intent.EXTRA_STREAM, mmsUri); intent.setType("image/png"); // 卸载应用 Uri uninstallUri = Uri.fromParts("package", "com.app.test", null); Intent intent = new Intent(Intent.ACTION_DELETE, uninstallUri); // 安装应用 Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(new File("/sdcard/test.apk"), "application/vnd.android.package-archive"); // 在Android Market中查找应用 Uri uri = Uri.parse("market://search?q=愤怒的小鸟"); Intent intent = new Intent(Intent.ACTION_VIEW, uri); |
需要注意的是,定义了Action的Activity,其他应用程序也可以调用,这样一来,程序之间的交流就很容易了,比如手机qq可以调用qq空间。所以,为了防止程序之间一些意料之外的影响,我们定义Action就要更详细更复杂一些,一般是包名+Action名,上面我用的“testIntent”就不太合理了,应该改成“com.jyx.demo.myapplication.testIntent”;同理,你也可以在自己的程序中调用其他程序的Action,比如在自己的程序中调用拨号面板:
1 2 3 4 5 |
Intent intent = new Intent(Intent.ACTION_DIAL); // 或者Intent intent = new Intent("android.intent.action.DIAL"); // Intent.ACTION_DIAL是内置常量,值为"android.intent.action.DIAL" startActivity(intent); |
此外,一个Activity可以处理多种Action,当然你的程序必须有足够的功能,Intent的Action只要是其中之一,就可以打开这个Activity。
1 2 3 4 5 6 7 8 9 |
<activity android:name=".IntentDemo2Activity"> <intent-filter> <action android:name="com.jyx.demo.myapplication.DAIL"/> <action android:name="com.jyx.demo.myapplication.SEND_EMAIL"/> <action android:name="com.jyx.demo.myapplication.SEND_MESSAGE"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity> |
对于一个Action字符串,系统有可能会找到一个Activity来处理,也可能找到多个,当然也有可能一个也找不到:
1.找到一个Activity
这样的话就直接打开这个Activity,无需多言。
2.找到多个Activity
这样的情况下,系统就会提示从多个Activity中选择一个打开,比如我再自己的程序里设置Action为:
“android.intent.action.DIAL”,这样别的程序调用拨号器时,系统就会询问,用哪一个。如下:
1 2 3 4 5 6 7 |
<activity android:name=".IntentDemo2Activity"> <intent-filter> <action android:name="android.intent.action.DIAL"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity> |
3.一个Activity都没找到
一个Activity都没找到的话,程序就会报错,会抛出ActivityNotFoundException。比如我们随便写一个Action:
1 2 3 |
Intent intent = new Intent("aaabbb111222"); startActivity(intent); |
所以要注意捕捉异常:
1 2 3 4 5 6 7 |
Intent intent = new Intent("aaabbb111222"); try{ startActivity(intent); }catch(ActivityNotFoundException e){ Toast.makeText(this, "找不到对应的Activity", Toast.LENGTH_SHORT).show(); } |
或者也可以用resoleActivity方法判断能否找到合适的Activity,如果没有,就停止startActivity
1 2 3 4 5 |
Intent intent = new Intent("aaabbb111222"); if(intent.resolveActivity(getPackageManager()) == null){ // 设置控件不可用 } |
注意resolveActivity方法返回值就是显式Intent上面讲到的ComponentName对象,一般情况下也就是系统找到的那个Activity。但是如果有多个Activity可供选择的话,则返回的Component是com.android.internal.app.ResolverActivity,也就是用户选择Activity的那个界面对应的Activity,这里不再多说。
1 2 3 4 5 6 7 |
Intent intent = new Intent("aaabbb111222"); ComponentName componentName = intent.resolveActivity(getPackageManager()); if(componentName != null){ String className = componentName.getClassName(); Toast.makeText(this, className, Toast.LENGTH_SHORT).show(); } |
以上就是我对显式Intent和隐式Intent的介绍,以后可能会出关于Intent的更多介绍,欢迎大家一起交流。
最后,欢迎指正,感谢阅读。
想获得去掉 5 元限制的证券账户吗?

如果您想去掉最低交易佣金 5 元限制,使用微信扫描左边小程序二维码,访问微信小程序「优财助手」,点击底部菜单「福利」,阅读文章「通过优财开证券账户无最低交易佣金 5 元限制」,按照文章步骤操作即可获得免 5 元证券账户,股票基金交易手续费率万 2.5。
请注意,一定要按照文章描述严格操作,如错误开户是无法获得免 5 元证券账户的。