14.Activity之间的Inter-process沟通
在Android里,一个Package可以含有多个Activity,这些Activity可以在同一个进程(Process)里执行;也可以在不同的进程里执行。基于Linux的安全限制,以及进程的基本特性(例如,不同进程的地址空间是独立的),Activity-a与Activity-b在同一个进程里执行时,两者沟通方便也快速。但是,当Activity-a与Activity-b分别在不同的进程里执行时,两者沟通就属于IPC跨进程沟通了,不如前者方便,也慢些。例如:
package xom.misoo.pkzz;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
public class ac01 extends Activityimplements OnClickListener {
private Button btn, btn4;
public static ac01 appRef =null;
private String feedback_data;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appRef = this;
setContentView(R.layout.main);
this.show_layout_01();
}
@Override
public void onResume(){
super.onResume();
setTitle(feedback_data);
}
void show_layout_01(){
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
btn = new Button(this);
btn.setBackgroundResource(R.drawable.water);
btn.setText("Edit");
btn.setOnClickListener(this);
LinearLayout.LayoutParams param =new LinearLayout.LayoutParams(150, 40);
param.topMargin = 5;
layout.addView(btn, param);
btn4 = new Button(this);
btn4.setBackgroundResource(R.drawable.face);
btn4.setText("Exit");
btn4.setOnClickListener(this);
layout.addView(btn4, param);
setContentView(layout);
}
public void setData(String x){
feedback_data = x;
}
public void onClick(View v){
if (v == btn){
Intent intent =new Intent(this, Activity_1.class);
this.startActivity(intent);
}
if(v.equals(btn4))
this.finish();
}
}
package xom.misoo.pkzz;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
public class Activity_1 extends Activityimplements OnClickListener {
private Button btn;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
btn = new Button(this);
btn.setBackgroundResource(R.drawable.music);
btn.setText("Edit");
btn.setOnClickListener(this);
LinearLayout.LayoutParams param =new LinearLayout.LayoutParams(150, 40);
param.topMargin = 5;
layout.addView(btn, param);
setContentView(layout);
ac01.appRef.setData("feedback from Activity_1.");
}
public void onClick(View arg0) {
finish();
}
}
其中的指令:ac01.appRef.setData("feedback from Activity_1."); 只有ac01与Activity_1两者都在同一个地址空间(即进程)才会有效。如果将AndroidManifest.xml里的<Activity>叙述修改为:
<activity android:name=".Activity_1" android:process=":remote">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
其令Activity_1在独立的进行里执行,则上述指令:ac01.appRef.setData("feedback from Activity_1."); 就不对了。
那么,这种跨进程的情形下,该如何沟通呢?
l 使用SharedPreference
可以使用:
import android.content.SharedPreferences.Editor;
于是,可在Activity_1里撰写指令如下:
public class Activity_1 extends Activityimplements OnClickListener {
private Button btn;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
…………………(省略)
Editor passwdfile = getSharedPreferences("ITEM", 0).edit();
passwdfile.putString("ITEM","feedback from Activity_1.");
passwdfile.commit();
}
…………………(省略)
}
并且,在ac01里撰写指令如下:
public class ac01 extends Activityimplements OnClickListener {
………………………
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
………………………
}
@Override
public void onResume(){
super.onResume();
SharedPreferences passwdfile = getSharedPreferences(
"ITEM", 0);
String im = passwdfile.getString("ITEM",null);
setTitle(im);
}
…………………………
}
这样就能Activity_1就能将数据传递给ac01了。
上述的ac01类别还可写为:
public class ac01 extends Activityimplements OnClickListener {
……………………
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
……………………
}
………………………
@Override
protected void onActivityResult(int requestCode,int resultCode, Intent data)
{
SharedPreferences passwdfile = getSharedPreferences(
"ITEM", 0);
String im = passwdfile.getString("ITEM",null);
setTitle(im);
}
public void onClick(View v){
……………………
Intent intent =new Intent(Intent.ACTION_EDIT, null);
this.startActivityForResult(intent, 0);
……………………
}
}
这两写法一样都能让Activity_1传回数据。
l 使用Intent对象
虽然透过Intent并非最快速,但却是最有弹性的。无论是同一进程或是跨进程的沟通都可以使用它。例如:
package com.misoo.pkzz;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
public class ac01 extends Activityimplements OnClickListener {
private Button btn, btn2, btn4;
public static ac01 appRef =null;
private final static String KKK = "AnyKey";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appRef = this;
setContentView(R.layout.main);
this.show_layout_01();
}
void show_layout_01(){
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
btn = new Button(this);
btn.setBackgroundResource(R.drawable.water);
btn.setText("Edit");
btn.setOnClickListener(this);
LinearLayout.LayoutParams param =new LinearLayout.LayoutParams(150, 40);
param.topMargin = 5;
layout.addView(btn, param);
btn2 = new Button(this);
btn2.setBackgroundResource(R.drawable.x_blue);
btn2.setText("shared data");
btn2.setOnClickListener(this);
layout.addView(btn2, param);
btn4 = new Button(this);
btn4.setBackgroundResource(R.drawable.face);
btn4.setText("Exit");
btn4.setOnClickListener(this);
layout.addView(btn4, param);
setContentView(layout);
}
@Override
protected void onActivityResult(int requestCode,int resultCode, Intent data)
{
SharedPreferences passwdfile = getSharedPreferences(
"ITEM", 0);
String im = passwdfile.getString("ITEM",null);
setTitle(im);
}
public void onClick(View v){
if (v == btn){
Intent intent =new Intent(Intent.ACTION_VIEW, null);
intent.putExtra(com.misoo.pkzz.ac01.KKK, "Ax004::Intent Extra Msg.");
this.startActivityForResult(intent, 0);
}
if(v.equals(btn2)){
SharedPreferences passwdfile = getSharedPreferences(
"ITEM", 0);
String im = passwdfile.getString("ITEM",null);
setTitle(im);
}
if(v.equals(btn4))
this.finish();
}
}
package com.misoo.pkzz;
import android.app.Activity;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
public class Activity_1 extends Activityimplements OnClickListener {
private Button btn;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
btn = new Button(this);
btn.setBackgroundResource(R.drawable.x_yellow);
btn.setText("Edit");
btn.setOnClickListener(this);
LinearLayout.LayoutParams param =new LinearLayout.LayoutParams(150, 40);
param.topMargin = 5;
layout.addView(btn, param);
setContentView(layout);
//-----------------------------------
String ss = this.getIntent().getStringExtra("AnyKey");
//-----------------------------------
Editor passwdfile = getSharedPreferences("ITEM", 0).edit();
passwdfile.putString("ITEM",ss);
passwdfile.commit();
}
public void onClick(View arg0) {
finish();
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.misoo.pkzz"
android:versionCode="1"
android:versionName="1.0.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".ac01"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".Activity_1" android:process=":remote">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>
这ac01透过Intent传递数据给Activity_1,而Activity_1则将之存入SharePreferences里,再回传给ac01类别。
<< 摘录结语 >>
上述谈到的情境是:
l 其ac01与Activity_1属于同一个Package。
l 其ac01与Activity_1 在同一个进程里执行,或者,各再独立的进程里执行。
然而,如果ac01与Activity_1分别属于不同的Package时,又如何呢?此时,就不能藉由SharePreferences来传递数据了,因为SharePreferences是属于某Package内的。至于IPC的详细沟通法,由另外的文章说明之。