Android Activity要点(2)
来源:互联网 发布:淘宝上传图片没反应 编辑:程序博客网 时间:2024/05/18 22:56
一、带返回值的Activity回退过程
一般情况下,我们要从当前Activity跳转到另一个Activity,采用的方法是通过startActivity(Intent)
来携带数据并实现跳转
有时候又需要跳转到的Activity能够在回退时返回处理结果给前一个Activity,这就要用到以下方法了
public void startActivityForResult(Intent intent, int requestCode)
该方法同样是用于实现Activity的跳转,不过多了一个int类型的请求码requestCode
requestCode用于标示当Activity回退时,处理结果是从哪一个Activity传递来的,因为当前Activity有可能需要跳转到多个Activity
此外,Activity类还包含有以下方法
protected void onActivityResult(int requestCode, int resultCode, Intent data)
requestCode即是请求码,resultCode用于标示数据处理结果,data用于携带数据
因此,我们可以用以下代码实现Activity的跳转
private int REQUEST_CODE = 10; Intent intent = new Intent(MainActivity.this, Main2Activity.class); Bundle bundle = new Bundle(); bundle.putString("requestText", "啊哈"); intent.putExtras(bundle); startActivityForResult(intent, REQUEST_CODE);
向Intent中传入需要传递给Main2Activity的数据
然后,在onActivityResult中处理Main2Activity回退后传递而来的数据处理结果,这里用Log来输出
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == RESULT_OK && requestCode == REQUEST_CODE) { Bundle bundle = data.getExtras(); Log.e("MainActivity", bundle.getString("responseText")); } super.onActivityResult(requestCode, resultCode, data); }
其中,需要判断requestCode是否与请求码相等
此外,查看源码可知,resultCode取值一般为以下三个,用来标示操作结果
/** Standard activity result: operation canceled. */ //标示操作取消 public static final int RESULT_CANCELED = 0; /** Standard activity result: operation succeeded. */ //标示操作成功 public static final int RESULT_OK = -1; /** Start of user-defined activity results. */ public static final int RESULT_FIRST_USER = 1;
以上都是在MainActivity中操作,此外还需要在Main2Activity中设置返回结果
先取出传递而来的数据requestText
private String requestText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); Intent intent = getIntent(); if (intent != null) { Bundle bundle = intent.getExtras(); if (bundle != null) { requestText = bundle.getString("requestText"); } } init(); }
通过setResult方法设置处理结果为RESULT_OK,并通过intent携带处理结果
public void init() { findViewById(R.id.response).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(); Bundle bundle = new Bundle(); bundle.putString("responseText", "收到第一个Activity的请求内容为:" + requestText); intent.putExtras(bundle); setResult(RESULT_OK, intent); finish(); } }); }
这样就可以实现当Activity回退时,携带处理结果到前一个Activity了
二、关于Activity启动模式的补充说明
在上一篇博文中已经介绍过Activity的四种启动模式了,这里再来补充一些内容
- singleTask
此为栈内复用模式
如果以在AndroidManifest中声明属性的方式来设定启动模式的话,如果不指定taskAffinity属性,该Acitvity只会存在于当前栈中
想要让Activity以单实例的方式存在于一个新的栈的话,可以这样声明:
<activity android:name=".Main2Activity" android:launchMode="singleTask" android:taskAffinity="com.custom.czy" />
注意,taskAffinity的值不能与包名相同,不然就相当于没有设置了
可以通过getTaskId()方法来查看当前Activity位于哪个栈,如:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.e("第一个Activity", getTaskId() + ""); }
- singleInstance
即单实例模式
采用此种模式的Activity均会独立存在于一个栈内,即使两个Activity的taskAffinity属性相同
例如
<activity android:name=".Main2Activity" android:launchMode="singleInstance" android:taskAffinity="com.custom.czy" /> <activity android:name=".Main3Activity" android:launchMode="singleInstance" android:taskAffinity="com.custom.czy" />
Main2Activity和Main3Activity均声明为singleInstance模式且栈名为com.custom.czy
但通过Log.e("Activity", getTaskId() + "");
查看,还是可以发现两个Activity存在于不同的栈中
三、Activity的隐式调用
隐式调用不需要明确指定要调用的Activity信息,而是根据Intent具有的信息去匹配目标组件的IntentFilter中所设置的过滤信息,如果匹配成功则启动,否则会报错
一个Activity可以包含有多个IntentFilter,只要Intent能够匹配其中一组< intent-filter >即可启动该Activity
IntentFilter具有的属性有:action、category、data
- action
action属性值是一个字符串,系统也为我们提供了多个action,如Intent.ACTION_VIEW可用于打开系统自带的浏览器
在 < intent-filter >中可以声明多个action,只要求Intent中携带的action字符串与其中一个相同即成功匹配该Activity
Intent中必须含有action属性,否则将直接匹配失败
<intent-filter> <action android:name="com.czy.action" /> <action android:name="com.czy1.action" /> <action android:name="com.czy1.action" /> <category android:name="android.intent.category.DEFAULT" /></intent-filter>
public void startActivity(View view) { Intent intent = new Intent("com.bb.hh"); intent.setAction("com.czy.action"); Log.e("++++++", intent.getAction()); startActivity(intent); }
这样依然可以成功启动Activity
- category
在< intent-filter >中同样可以设定多个category属性,且Intent也可以通过addCategory(String category)添加多个category
与action属性不同的是,只要是在Intent中包含的category值,< intent-filter >都必须有category与之一一匹配,否则匹配失败
需要注意的是,系统在startActivity(Intent intent)的时候,会自动为Intent添加一个默认的category值,即:android.intent.category.DEFAULT
所以为了让Activity可以通过隐式调用的方式启动,需要在< intent-filter >同样为之添加一个默认的category值
如上述代码所示
- data
data属性用于指定当前活动能够响应什么类型的数据
如系统自带的浏览器自然就能响应http模式的网络连接要求,因此我们可以用隐式调用的方式来调用浏览器打开指定网页
Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("http://www.baidu.com")); startActivity(intent);
如果过滤规则中设置了data属性,则Intent中也必须含有data属性且相同才能匹配成功
data包含的属性值有:
<data android:scheme="string" android:host="string" android:port="string" android:path="string" android:pathPattern="string" android:pathPrefix="string" android:mimeType="string"/>
data由两部分组成,mimeType和URI
mimeType指媒体类型,可以是:image/jpeg、video/*,用于表示图片、文本、视频等不同的媒体格式
URL的结构如下所示:
< scheme>://< host>:< port>/[< path>|< pathPrefix>|< pathPatten>]
scheme:URI的模式,如http,file,content,默认值为(content和file)
host:URI的主机名,比如www.baidu.com
port:URI的端口号
path、pathPatten和pathPrefix这三个参数表示路径信息
如,可以设置某Activity能够处理的数据类型为图片image
<activity android:name=".Main2Activity"> <intent-filter> <action android:name="com.czy.action" /> <action android:name="com.czy1.action" /> <action android:name="com.czy1.action" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.czy" /> <data android:mimeType="image/*" /> </intent-filter></activity>
则可以通过设置mimeType属性来启动该Activity
public void startActivity(View view) { Intent intent = new Intent("com.bb.hh"); intent.setAction("com.czy.action"); intent.addCategory("android.intent.category.czy"); intent.setType("image/png"); startActivity(intent); }
或者为Intent设置完整的data属性
public void startActivity(View view) { Intent intent = new Intent("com.bb.hh"); intent.setAction("com.czy.action"); intent.addCategory("android.intent.category.czy"); intent.setDataAndType(Uri.parse("file://abc"),"image/png"); startActivity(intent); }
此外,由于通过隐式调用有可能因为匹配不成功而导致报错,所以在调用之前可以先判断当前是否有合适的Activity
Intent intent = new Intent("com.bb.hh"); intent.setAction("com.czy.action"); intent.addCategory("android.intent.category.czy"); intent.setDataAndType(Uri.parse("file://abc"), "image/png"); ComponentName componentName = intent.resolveActivity(getPackageManager()); if (componentName != null) { String name = componentName.getClassName(); Log.e("MainActivity:", "匹配成功:" + name); startActivity(intent); } else { Log.e("MainActivity:", "匹配失败"); }
如果匹配失败,resolveActivity方法就会返回null,否则就会返回匹配度最高的Activity信息
- Android Activity要点(2)
- Android Activity要点(1)
- Android的Activity要点
- Android开发--创建Activity 要点、注册
- Android Activity生命周期以及onSaveInstanceState、onRestoreInstanceState要点备忘
- Android Activity页面加载时间性能分析,以及改进要点
- Android Activity生命周期以及onSaveInstanceState、onRestoreInstanceState要点备忘
- Android技术要点【一】四大组件之Activity
- Activity的要点
- 创建activity要点
- Activity要点总结
- 创建activity的要点
- Activity生命周期要点分析
- Activity工作流学习要点
- Activity工作流学习要点
- Android知识要点整理(1)---- Android 2D动画
- android application 要点备忘 2
- Android面试要点(1)
- 占位
- Java中的对象序列化
- 占位
- JVM 深入笔记(3)垃圾标记算法
- 占位
- Android Activity要点(2)
- 函数指针的作用以及好处
- UVALive 7226 Coin Swap
- 占位
- 占位
- 占位
- 占位
- 占位
- 占位