Android 消息通信之Activity间消息传递

消息通信机制

Android 开发之中我们常常需要应用到消息传递的机制,消息的传递有多种方式。消息传递的作用不必多说,主要是在不同的组件之间传播消息或者共享某些状态等,以下是几种常用的消息传递机制:

  1. Intent
  2. 静态变量
  3. 全局变量 及Application
  4. Android系统剪切板
  5. 本地化存储方式
  6. Andorid组件
  7. EventBus

1. Intent

这是很常见的方式了,不必多说,简单的写法如下:

Intent intent = new Intent();
intent.putExtra("send","发送了消息");
intent.setClass(MainActivity.this,ReceiveActivity.class);
startActivity(intent);

这样就可以在目标Activity中接收到消息。
下图是Intent可以传递的数据大全,只要为每个数据设置不同的name就可以通过name取出。
Intent可放入的数据类型大全

2. 静态变量 && 3 全局变量及Application &&4 Android 系统剪切板

这三种方式其实非常相似,静态变量和全局变量都可以采用static的方式来定义,如果采用这种方式还是推荐用一个专门的类结合单体模式进行管理,尽量减少对内存的消耗。
而使用系统剪切板的方式一般也很少用,比较多限制,容易丢失数据,几乎没有看到有这样用的。
这里还有利用Application进行共享Handler来消息传递,方法很简单,就是在Application中定义一个全局的Handler,虽然这种方法可以实现,但是却保留了在整个App中保留了全局的Handler,如果在Handler的设置中引用了某个Activity,就容易造成内存泄露了。

5. 本地化存储方式

本地存储方式有如下三种:

SharedPreference
SQLite
File

这三种方式的好处就是他们是持久存储的,只要不卸载APP或者不删除文件就可以一直保存下去,而且也几乎没有大小的限制,可以做一些统计。不过缺点也比较明显,这三种方式最好是采用多线程来进行读写,尤其是数据量大的时候,我们知道,IO的操作是非常耗费时间的,所以尽量不要在UI线程中使用这三种方式读写。

示例代码:

SharedPreference:

// 发送消息
SharedPreferences.Editor editor = MainActivity.this.getSharedPreferences("SEND", Context.MODE_PRIVATE).edit();
editor.putString("SEND","SharedPreferences的消息");
editor.apply();
startActivity(new Intent(MainActivity.this,ReceiveActivity.class));
// 接收消息
SharedPreferences sharedPreferences = getSharedPreferences("SEND", MODE_PRIVATE);
textView.setText(sharedPreferences.getString("SEND", ""));

附支持的数据类型如下:
这里写图片描述

SQLite

SQLite需要先创建数据库,后面向数据库中插入和读取数据实现信息共享。
首先要继承SQLiteOpenHelper并在onCreate方法中创建数据库:

sqLiteDatabase.execSQL("CREATE TABLE Teacher(teacherId INTEGER PRIMARY KEY" +
           " AUTOINCREMENT,userId VARCHAR(20) UNIQUE,name VARCHAR(20),password VARCHAR(20))");

向数据库中插入:

String type = "Teacher";
sqLiteDatabase.execSQL("INSERT INTO " + type + "(userId,name,password) values (?,?,?)",
                    new String[]{userId, userName, userPassword});

从数据库中读取信息:

String type = "Teacher";
Cursor cursor = sqLiteDatabase.rawQuery("SELECT * FROM " + type + " WHERE userId = ?",
         new String[]{userId.getText().toString()});
if(cursor.moveToFirst()){
         String userId = cursor.getString(cursor.getColumnIndex("userId"));
         String name = cursor.getString(cursor.getColumnIndex("name"));
}
cursor.close();

File

文件方式要记得申请权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

写入数据:

try {
    File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/data/temp.txt");
    FileOutputStream out = new FileOutputStream(file);
    out.write("message".getBytes(Charset.forName("UTF-8")));
    out.flush();
    out.close();
} catch (IOException e) {
    e.printStackTrace();
}

读取数据:

try {
    FileInputStream in = new FileInputStream(Environment.getExternalStorageDirectory().getAbsolutePath() + "/temp.txt");
    byte[] reader = new byte[256];
    int read = in.read(reader);
    String content = "";
    if (read > 0)
        content = new String(reader, 0, read, Charset.forName("UTF-8"));
    Toast.makeText(this, content, Toast.LENGTH_SHORT).show();
} catch (IOException e) {
    e.printStackTrace();
}

6.Android 组件

Broadcast方式

使用组件也就是说利用Broadcast进行消息传递。
如果说使用Android 进行消息传递的话,Broadcast是最好的了,顾名思义的我们知道,广播就是有一个发送消息和接受消息的过程,所以可以用于消息传递。
示例:
注册广播和接受消息

        // 定义广播
        final Button broadButton = findViewById(R.id.broadcast);
        final BroadcastReceiver receiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                broadButton.setText("" + intent.getStringExtra("data"));
            }
        };
        broadButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                registerReceiver(receiver,new IntentFilter("broadsend.action"));
                startActivity(new Intent(MainActivity.this,ReceiveActivity.class));
            }
        });

发送广播:

                Intent intent = new Intent("broadsend.action");
                intent.putExtra("data","send");
                sendBroadcast(intent);

这种方式有一些限制,因为接收事件要比发送事件先定义好,所以只能在当前Activity中注册广播,在跳转的Activity发送,所以严格说这不能算是消息传递,因为是单向的。

Service方式

Service可以结合Broadcast进行消息传递,不过这样子就不能算是Service了。
使用Service进行消息传递,我们可以定义接口,并利用接口进行消息传递。
定义消息接收的接口:

    public static MessageCallback messageCallback = new MessageCallback() {
        @Override
        public void onMessage(String message) {
            Log.d("tag","" + message);
        }
    };
    public interface MessageCallback{
        public void onMessage(String message);
    }

进行消息发送:

MainActivity.messageCallback.onMessage("message");

有的人说这种方式不久和共享变量一样了吗,不不不,这是完全不一样的,如果是共享变量的话,当变量被改变了是不是还得程序员或者用户去响应这种改变呢,这就很不好了,而采用这种静态接口的方法,只要函数被调用,就立刻可以进行响应并处理,不是很方便吗。当然也可以想办法将接口的对象进行传递,例如利用Broadcast来进行传递。

。。。 未完待续

EventBus

EventBus 是一款针对Android的发布以及订阅事件总线,使用它可以很方便的进行信息传递,而且使用起来很方便。
首先是定义一个消息:

public class Event {
    private String message;
    public Event(){
        message = "EventBus message";
    }

    public void setMessage(String message){
        this.message = message;
    }

    public String getMessage(){
        return message;
    }
}

发送消息:
这里使用了postSticky,这是发送的粘性广播,使用这个发送就可以先发送信息再进行注册,后注册的也能接收到前面发送的广播。当然还有其他的使用方式,可以查查api文档。

EventBus.getDefault().postSticky(new Event());
startActivity(new Intent(MainActivity.this,ReceiveActivity.class));

注册事件的订阅者:

EventBus.getDefault().register(this);

接受粘性广播:

@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)
public void onEventThread(Event event) {
    textView.setText(event.getMessage());
}

总结及对比

对上面所说的各种消息传递和通信进行一个对比,Intent的方法是不太适合大量的数据传递的,如果大于0.5M会抛出异常。而才用静态变量或者全局变量则占用内存较大,且不易管理。才用系统剪切板的很少见,以为容易丢失数据。本地化的存储方式需要较多的时间,但是这种方式存储的数据是持久化的,可以用于故障恢复等场景,不过就是需要考虑IO的时间。使用Androdi组件的Broadcast或者service在小数据传输时例如仅仅是Activity跳转传输一两个变量,就未免太大才小用了。EventBus是基于事件订阅和发布的,使用上很方便。总之,就是要根据自己的应用场景来合理选择。

猜你喜欢

转载自blog.csdn.net/qq_34911465/article/details/79420559