在 Android 开发中,我们经常需要在不同的 Java 文件(如类或活动)之间传递数据。本文将介绍两种主要的数据传递方式:广播(Broadcast)和 Handler。我将以我开发的一个实例为例,展示如何在 TcpServer(Tcp服务器工具类)和 SerialPortActivity(主线程活动)之间进行数据传递。
使用广播
在 TcpServer 中,当需要将数据传递给 SerialPortActivity 时,可以发送一条广播。SerialPortActivity 接收到该广播后即可处理数据。
在 TcpServer 中发送广播的代码如下:
// 发送广播 Intent intent = new Intent("com.example.ACTION_TCP_DATA"); intent.putExtra("data", tcpData); sendBroadcast(intent);
在 SerialPortActivity 中注册广播接收器:
// 注册广播接收器 private void registerReceiver() { IntentFilter filter = new IntentFilter("com.example.ACTION_TCP_DATA"); BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("com.example.ACTION_TCP_DATA")) { String tcpData = intent.getStringExtra("data"); // 在此处处理tcpData } } }; registerReceiver(receiver, filter); }
使用 Handler
另一种方式是在 SerialPortActivity 中创建一个 Handler 对象,并将其传递给 TcpServer。在 TcpServer 中发送数据时,使用该 Handler 对象发送消息,然后在 SerialPortActivity 中通过覆写该 Handler 的 handleMessage() 方法来处理消息。
在 SerialPortActivity 中创建 Handler 对象:
private Handler mHandler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_TCP_DATA: String tcpData = (String) msg.obj; // 在此处处理tcpData break; default: super.handleMessage(msg); break; } } };
在 TcpServer 中发送消息给 SerialPortActivity:
// 发送消息 Message message = Message.obtain(); message.what = MSG_TCP_DATA; message.obj = tcpData; mHandler.sendMessage(message);
选择广播还是 Handler 主要取决于具体需求。如果数据需要被多个组件(如其他活动或服务)共享,那么广播可能是更好的选择。如果只有一个组件需要处理数据,使用 Handler 会更加简单直接。
就性能而言,Handler 更高效。广播需要进行广播注册、解注册等操作,并且可以被多个组件接收,因此一旦有新的广播到来,系统需要遍历所有已注册的接收器,并且复制 Intent 的内容,然后将广播传递给所有接收器。这些操作会占用相当大的系统资源,导致性能下降。相比之下,Handler 基于消息队列实现,不需要注册和注销过程,也不需要拷贝 Intent,只需往消息队列中添加消息。接收到消息后,Handler 会直接调用主线程的 Looper.loop() 方法,将消息分发给对应的处理方法。
// 发送消息 Message message = Message.obtain(); message.what = SerialPortActivity.MSG_TCP_DATA; message.obj = tcpData; mHandler.sendMessage(message);
如果只在单个组件中传递数据,建议使用 Handler;如果需要多个组件共享数据,则可以考虑使用广播。
定义一个名为 MSG_TCP_DATA 的 int 常量,可以在 SerialPortActivity 中进行定义,例如:
public static final int MSG_TCP_DATA = 1;
在 TcpServer 中就可以直接引用该常量了,例如:
需要注意的是,在 TcpServer 中需要获取 SerialPortActivity 的 Handler 对象才能调用 sendMessage() 方法。为避免内存泄漏,建议使用弱引用(WeakReference)来保存 Handler 对象的引用。以下是一个示例实现:
public class TcpServer { private WeakReference<Handler> mHandlerRef; public void setHandler(Handler handler) { mHandlerRef = new WeakReference<>(handler); } // 在需要发送数据时调用此方法 public void sendData(String data) { if (mHandlerRef != null && mHandlerRef.get() != null) { Handler handler = mHandlerRef.get(); Message message = handler.obtainMessage(SerialPortActivity.MSG_TCP_DATA, data); handler.sendMessage(message); } } }
在 SerialPortActivity 中,通过 setHandler() 方法将 Handler 对象传递给 TcpServer:
TcpServer tcpServer = new TcpServer(); tcpServer.setHandler(mHandler);
这样就可以在 TcpServer 中使用 SerialPortActivity 定义的常量 MSG_TCP_DATA,并且避免了内存泄漏问题