Android 开发中,如何实现多个 Activity 相互通信?
其实上述这个问题是十分简单的,但是还是让我思考了很久,也在网上查询了很多文章去了解;因为我在想是把所有能想到的通信方式都列出来呢,还是只列出来重点的、常用的,良久,我还是选择了后者
在开发中如若遇到多个 Activity 的传值问题、相邻两个之间的传值、或者多个三个以上之间的传值问题;解决方案大抵上有以下三种
1、注册或者登陆成功后 跳到某一新 Activity传值问题 2、注册界面需要选择性别 需要打开一个新的界面选择里面的信息回到当前 Activty 的传值问题 3、设置界面需要某一界面选择的图片(但是还没上传服务),如果中间相隔几种 Activty 时的传值
再来说下目前 Activity 之间的数据通信方式主要有几种:
- Intent
- 借助类的静态变量
- 借助全局变量 /Application
- 借助外部工具 – 借助 SharedPreference – 使用 Android 数据库 SQLite – 赤裸裸的使用 File – Android 剪切板
- 借助 Service
接下来我们依次来解析一下:
1) 在 Intent 跳转时携带数据Intent 是 Android 四大组件(Activity、Service、BroadcastReceiver、ContentProvider)之间通信的纽带,在 Intent 中携带数据也是四大组件之间数据通信最常用、最普通的方式;常规写法如下:
//创建用于封装数据的Bundle对象
Bundle bundle = new Bundle();
bundle.putString("name", "WangJie");
bundle.putInt("age", 23);
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
//将Bundle对象嵌入Intent中
intent.putExtras(bundle);
startActivity(intent);
更简洁,也是更智能的写法是:
//创建Intent对象
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
//程序自动创建Bundle,然后将对Intent添加的数据装载在Bundle中,对用户透明
intent.putExtra("name", "WangJie");
intent.putExtra("age", 23);
startActivity(intent);
在 SecondActivity 中获取 intent 跳转时携带的数据:
//intent要用this的getIntent()获取
Intent intent = getIntent();
//用intent.getXXXExtra("key-name")或是intent.getXXXExtra("key-name", default-value)获取值
String name = intent.getStringExtra("key1");
int age = intent.getIntExtra("key2", 0);
2)借助类的静态变量来实现
由于类的静态成员可以通过 “className.fileName” 来访问,故而可以供两个 Activity 访问从而实现 Activity 之间的数据通信
在 MainActivity 中:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//先查看一下未更改的值
SecondActivity.age = 23;
Button btn = (Button) findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//到SecondActivity中查看对age更改是否有效
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);
}
});
}
}
在 SecondActivity 中:
public class SecondActivity extends AppCompatActivity {
//声明为静态file
static int age = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
//在MainActivity中更改了age,所以这里肯定不是"1"
Toast.makeText(this, "在MianActivity中更改了age后的值 = " + age, Toast.LENGTH_SHORT).show();
}
}
3)借助全局变量来实现 /Application
和类的静态变量类似,但是这个类作为单独第三个类(最好是写一个 Application 类):
public class ForExampleClass {
//此处声明一个public static 成员来实现数据通信
public static int age = 0;
}
在一个 Activity 中对类的静态变量进行访问和更改:
//先查看一下未更改的值
Toast.makeText(this, "age = " + ForExampleClass.age, Toast.LENGTH_SHORT).show();
//在一个Activity中对类的静态变量进行变更
ForExampleClass.age = 23;
然后在另一个 Activity 中访问该变量,来验证这种通信方式:
//先查看一下未更改的值
//在另一个Activity中访问更改后的变量来验证
Toast.makeText(this, "更改后的age = " + ForExampleClass.age, Toast.LENGTH_SHORT).show();
4)借助外部存储来实现通讯
4-1)使用 SharedPreference 实现 Activity 之间的数据通信
SharedPreference 是 Android 中最简单的文件本地化存储方式,Android API 也提供相当简单的方式来进行读写操作;下面简单看一下SharedPreference的使用:
首先,我们在 MainActivity 中先查看一下 SharedPreference 文件中的初始值,然后做更改:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取Application的SharedPreference对象
SharedPreferences sp = getApplication().getSharedPreferences("myInfo", 0);
//get方法获取值,如果没有存储对应的key-value则返回get方法给的默认值
String name = sp.getString("name", "null");
int age = sp.getInt("age", 0);
boolean isStudent = sp.getBoolean("isStudent", false);
//查看一下初始值
Toast.makeText(this, "MianActivity中:\n" + "name = " + name
+ "\nage = " + age + "\nisStudent = " + isStudent, Toast.LENGTH_SHORT).show();
//在写入时要先获取SharedPreference的Editor对象,经过Editor进行写入
SharedPreferences.Editor editor = sp.edit();
editor.putString("name", "WangJie");
editor.putInt("age", 23);
editor.putBoolean("isStudent", true);
//put完成后一定要commit(),否则不会生效
editor.commit();
Button btn = (Button) findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);
}
});
}
}
然后,在 SecondActivity 中再次查看:
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
//获取Application的SharedPreference对象
//注意"name"值一定要一致,否则会新建一个SharedPreference对象(本地存储新增一个文件)
SharedPreferences sp = getApplication().getSharedPreferences("myInfo", 0);
String name = sp.getString("name", "null");
int age = sp.getInt("age", 0);
boolean isStudent = sp.getBoolean("isStudent", false);
Toast.makeText(this, "SecondActivity中查看:\n" + "name = " + name
+ "\nage = " + age + "\nisStudent = " + isStudent, Toast.LENGTH_SHORT).show();
}
}
5)借助Service来实现
既然存在外部太慢,那么还是在内存级别解决问题好了,这时候,你可能就需要请出 Android 四大组件之一的 Service 了;Service设计的本意,就是提供一些后台的服务,数据存取,也可以归于其职责的一部分
Service 是提供了直连机制,调用的 Activity,可以通过 bindService 方法,与目标 Service 建立一条数据通路,拿到 IBinder;这样,通过 Android 提供的 IPC 模型(进程间通信),就可以进行远程方法的调用和数据的传输了。
通过这种模式,可以解决一定问题,但是对于 Service 来说,实在是有点大材小用了,Service 的专长,不是在数据,还是在逻辑;对于传数据而言,Service 还是重量了一点,不但是有连接耗精力,传输经由 IPC,写起来也够费劲;而且作为组件,Service 随时可能死掉,你还是要费劲心机的处理数据的持久化,得不偿失
上边分析了那么多, 看了那么一大堆的代码,我们清楚的了解到了 Activity 之间的相互通信到底有哪些;像这些关于底层的技术点,还有许多需要我们去了解学习;在这里提供一份 Android FrameWork 源码解析 思维导图及学习手册,以便大家能够更好的学习底层知识
Android FrameWork 源码解析思维导图- 从应用程序进程到管理者进程
- 应用程序进程向管理者进程发送消息
- 从管理者进程到应用程序进程
- 管理者进程向应用程序进程发送消息
- 用户进程接收消息
- WindowManagerImpl & WindowManagerGlobal
- ViewRootImpl
- 从应用进程到管理者进程
- 从管理者进程到应用进程
由于篇幅原因,仅展示部分知识点图片;上述的资料都是免费的,有需要的小伙伴:可点击此处查看直达方式 或者私信发送 “进阶” ,即可获取
好了,以上就是今天要分享的内容,大家觉得有用的话,可以点赞分享一下;如果文章中有什么问题欢迎大家指正;欢迎在评论区或后台讨论哈~