Activity之间的通信方式

参考博客:

https://blog.csdn.net/a_running_wolf/article/details/48813995

https://blog.csdn.net/a_running_wolf/article/details/48826495

https://blog.csdn.net/wulianghuan/article/details/8583598#comments

Activity之间的数据通信方式主要有以下????种:

  • Intent
  • 借助类的静态变量
  • 借助全局变量/Application
  • 借助外部工具 
    – 借助SharedPreference 
    – 使用Android数据库SQLite 
    – 赤裸裸的使用File 
    – Android剪切板
  • 借助Service

(1) 在Intent跳转时携带数据 
Intent是Android四大组件(Activity、Service、BroadcastReceiver、ContentProvider)之间通信的纽带,在Intent中携带数据也是四大组件之间数据通信最常用、最普通的方式。常规写法如下:

 
  1. //创建用于封装数据的Bundle对象

  2. Bundle bundle = new Bundle();

  3. bundle.putString("name", "WangJie");

  4. bundle.putInt("age", 23);

  5.  
  6. Intent intent = new Intent(MainActivity.this, SecondActivity.class);

  7. //将Bundle对象嵌入Intent中

  8. intent.putExtras(bundle);

  9. startActivity(intent);

更简洁,也是更智能的写法是:

 
  1. //创建Intent对象

  2. Intent intent = new Intent(MainActivity.this, SecondActivity.class);

  3. //程序自动创建Bundle,然后将对Intent添加的数据装载在Bundle中,对用户透明

  4. intent.putExtra("name", "WangJie");

  5. intent.putExtra("age", 23);

  6. startActivity(intent);

在SecondActivity中获取intent跳转时携带的数据:

 
  1. //intent要用this的getIntent()获取

  2. Intent intent = getIntent();

  3. //用intent.getXXXExtra("key-name")或是intent.getXXXExtra("key-name", default-value)获取值

  4. String name = intent.getStringExtra("key1");

  5. int age = intent.getIntExtra("key2", 0);

(2)借助类的静态变量来实现 
由于类的静态成员可以通过“className.fileName”来访问,故而可以供两个Activity访问从而实现Activity之间的数据通信: 
在MainActivity中:

 
  1. public class MainActivity extends AppCompatActivity {

  2.  
  3. @Override

  4. protected void onCreate(Bundle savedInstanceState) {

  5. super.onCreate(savedInstanceState);

  6. setContentView(R.layout.activity_main);

  7.  
  8. //先查看一下未更改的值

  9. SecondActivity.age = 23;

  10.  
  11. Button btn = (Button) findViewById(R.id.button);

  12. btn.setOnClickListener(new View.OnClickListener() {

  13. @Override

  14. public void onClick(View v) {

  15. //到SecondActivity中查看对age更改是否有效

  16. Intent intent = new Intent(MainActivity.this, SecondActivity.class);

  17. startActivity(intent);

  18. }

  19. });

  20. }

  21. }

在SecondActivity中:

 
  1. public class SecondActivity extends AppCompatActivity {

  2. //声明为静态file

  3. static int age = 0;

  4. @Override

  5. protected void onCreate(Bundle savedInstanceState) {

  6. super.onCreate(savedInstanceState);

  7. setContentView(R.layout.activity_second);

  8.  
  9. //在MainActivity中更改了age,所以这里肯定不是"1"

  10. Toast.makeText(this, "在MianActivity中更改了age后的值 = " + age, Toast.LENGTH_SHORT).show();

  11. }

  12. }

  • 看结果: 
    SecondActivity中的结果

(3)借助全局变量来实现/Application 
和类的静态变量类似,但是这个类作为单独第三个类(最好是写一个Application类):

 
  1. public class ForExampleClass {

  2. //此处声明一个public static 成员来实现数据通信

  3. public static int age = 0;

  4. }

在一个Activity中对类的静态变量进行访问和更改:

 
  1. //先查看一下未更改的值

  2. Toast.makeText(this, "age = " + ForExampleClass.age, Toast.LENGTH_SHORT).show();

  3. //在一个Activity中对类的静态变量进行变更

  4. ForExampleClass.age = 23;

然后在另一个Activity中访问该变量,来验证这种通信方式:

 
  1. //在另一个Activity中访问更改后的变量来验证

  2. Toast.makeText(this, "更改后的age = " + ForExampleClass.age, Toast.LENGTH_SHORT).show();

  • 看结果: 
    在前一个Activity中变更前的值: 
    改前 
    在后一个Activity中变更后的值: 
    改后 
    这是使用全局变量的本质,但是Java是编程思想不建议这样的写法,所以最好是将ForExampleClass继承Application,在应用的所有Activity都可以访问,并且要用get\set方法进行访问,可以看一下 
    @彬彬的博客Android使用全局变量和@邬良欢Android入门篇三:使用静态变量在Activity之间传递数据。 
    其实上边“(2)借助类的静态变量来实现”和“(3)借助全局变量来实现”很类似,只是在借助类的静态变量时接收信息的Activity中声明静态file,在别的Activity中做更改,而借助全局变量(建议继承Application,此时就是所谓的“使用Application”,因为Application类在本应用所有Activity中都可以访问,但是要注意内存泄漏的问题)是另外声明一个类,所有Activity共享这个类而已

 

下面这里附上使用Activity来完成数据传递的Demo,这种方法适用于我们要用intent来传输大数据时,因为intent的传输数据容量最多10m?反正当时我多传几张图片就报错,查了一下定义一个什么文件通过get/set操作来获取。但是这种方法也有它的弊端:一个Application里只能有一个andoid:.name的定义,如果存在多个不同的话只能把它们都合并到同一个类里面。

 

 

(4)借助外部存储来实现通讯

(4-1)使用SharedPreference实现Activity之间的数据通信

        SharedPreference是Android中最简单的文件本地化存储方式,Android API也提供相当简单的方式来进行读写操作。下面简单看一下SharedPreference的使用:

首先,我们在MainActivity中先查看一下SharedPreference文件中的初始值,然后做更改:

 
  1. public class MainActivity extends AppCompatActivity {

  2.  
  3. @Override

  4. protected void onCreate(Bundle savedInstanceState) {

  5. super.onCreate(savedInstanceState);

  6. setContentView(R.layout.activity_main);

  7.  
  8. //获取Application的SharedPreference对象

  9. SharedPreferences sp = getApplication().getSharedPreferences("myInfo", 0);

  10. //get方法获取值,如果没有存储对应的key-value则返回get方法给的默认值

  11. String name = sp.getString("name", "null");

  12. int age = sp.getInt("age", 0);

  13. boolean isStudent = sp.getBoolean("isStudent", false);

  14. //查看一下初始值

  15. Toast.makeText(this, "MianActivity中:\n" + "name = " + name

  16. + "\nage = " + age + "\nisStudent = " + isStudent, Toast.LENGTH_SHORT).show();

  17.  
  18. //在写入时要先获取SharedPreference的Editor对象,经过Editor进行写入

  19. SharedPreferences.Editor editor = sp.edit();

  20. editor.putString("name", "WangJie");

  21. editor.putInt("age", 23);

  22. editor.putBoolean("isStudent", true);

  23. //put完成后一定要commit(),否则不会生效

  24. editor.commit();

  25.  
  26. Button btn = (Button) findViewById(R.id.button);

  27. btn.setOnClickListener(new View.OnClickListener() {

  28. @Override

  29. public void onClick(View v) {

  30. //

  31. Intent intent = new Intent(MainActivity.this, SecondActivity.class);

  32. startActivity(intent);

  33. }

  34. });

  35. }

  36. }

然后,在SecondActivity中再次查看:
 
  1. public class SecondActivity extends AppCompatActivity {

  2. @Override

  3. protected void onCreate(Bundle savedInstanceState) {

  4. super.onCreate(savedInstanceState);

  5. setContentView(R.layout.activity_second);

  6.  
  7. //获取Application的SharedPreference对象

  8. //注意"name"值一定要一致,否则会新建一个SharedPreference对象(本地存储新增一个文件)

  9. SharedPreferences sp = getApplication().getSharedPreferences("myInfo", 0);

  10. String name = sp.getString("name", "null");

  11. int age = sp.getInt("age", 0);

  12. boolean isStudent = sp.getBoolean("isStudent", false);

  13.  
  14. Toast.makeText(this, "SecondActivity中查看:\n" + "name = " + name

  15. + "\nage = " + age + "\nisStudent = " + isStudent, Toast.LENGTH_SHORT).show();

  16. }

  17. }

        结果看图:

MainActivity结果SecondActivity

        不足之处在于——从SharedPreference的API就可以看出,采用SharedPreference只能存取标准数据类型的变量值int、float、long、boolean、String。对与一些复杂类型的就捉襟见肘了。

(4-2)使用SQLite来实现数据共享通信

         和SharedPreference类似,SQLite也是Android提供的一种数据持久化操作方式之一。SQLite是遵循SQL标准的数据库,支持标准SQL语句进行操作,当然Android也为对SQL不熟悉的开发者提供了相应的API(但这些API大多需要传入很多参数,个人觉得很不好用,还是建议学学 SQL,毕竟Android也只用一些简单的增删改查)。

数据库是Application的私有文件,如果其他应用想访问该数据要用过ContentProvider来实现。比如你用系统的录音机组件即时搞一段音频信息,它不是返回可能大到恐怖的录音数据,而是会返回给你一个Uri,它标明了这份数据在ContentProvider的地址信息,拿着这个Uri,领取数据就好,就像一张门票。不同Activity可以通过访问或更改数据库中对应的数据项来实现两个(多个Activity)之间的数据通信。

这里就不举例使用了,以后有机会会专门说说SQLite的使用。

(4-3)直接使用File来实现

        其实从本质属性来讲,使用SharedPreference和SQLite来存取数据都是使用File来存取数据的方式——SharedPreference是存放在data/data/应用包名/shared_prefs目录下后缀为.xml的文件,SQLite是存放在data/data/应用包名/databases目录下的后缀为.db3的文件。只是Android系统为这些文件存取专门格式化了存取格式而已,本质上还是文件读写。

        当然,如果你足够淡定,也可以用赤裸裸的File来存储。如果这个文件存在手机私有目录下,那就内部使用,放在SD卡上,那就可以所有应用,一切分享。但是这样暴力的方式需要你在文件读写时进行大量的额外工作。

     基于这样外部存储的数据传输,优缺点显而易见,它解决了困扰Intent的传输路径复杂,不利于传输大批量数据的问题,但同时,它有留下了效率隐患,复杂了编程模型。因为面对外部存储,开发者必须要考虑效率问题,很多时候,多线程就会被提上议程,这样,想不麻烦,都不行鸟。

(5)借助Service来实现

既然存在外部太慢,那么还是在内存级别解决问题好了,这时候,你可能就需要请出Android四大组件之一的Service了。Service设计的本意,就是提供一些后台的服务,数据存取,也可以归于其职责的一部分。

Service是提供了直连机制,调用的Activity,可以通过bindService方法,与目标Service建立一条数据通路,拿到IBinder。这样,通过Android提供的IPC模型(进程间通信),就可以进行远程方法的调用和数据的传输了。

通过这种模式,可以解决一定问题,但是对于Service来说,实在是太大才小用了,Service的专长,不是在数据,还是在逻辑。对于传数据而言,Service还是重量了一点,不但是有连接耗精力,传输经由IPC,写起来也够费劲。而且作为组件,Service随时可能死掉,你还是要费劲心机的处理数据的持久化,得不偿失。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值