Android 广播 - 组件通信

一、Service 通知 Activity 更新 UI

1、Service
java 复制代码
public class BroadcastConstants {
    public static final String ACTION_UPDATE_UI = "com.example.ACTION_UPDATE_UI";
    public static final String EXTRA_DATA = "extra_data";
}
java 复制代码
public class MyService extends Service {

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        // 模拟后台任务
        new Thread(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // 发送广播通知 Activity
            Intent broadcastIntent = new Intent(BroadcastConstants.ACTION_UPDATE_UI);
            broadcastIntent.putExtra(BroadcastConstants.EXTRA_DATA, "来自 Service 的数据");
            sendBroadcast(broadcastIntent);
        }).start();

        return START_NOT_STICKY;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}
2、Activity
xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".communication.WorkActivity">

    <TextView
        android:id="@+id/tv_result"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
java 复制代码
public class WorkActivity extends AppCompatActivity {

    private TextView tvResult;

    private final BroadcastReceiver uiReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (BroadcastConstants.ACTION_UPDATE_UI.equals(intent.getAction())) {
                String data = intent.getStringExtra(BroadcastConstants.EXTRA_DATA);
                tvResult.setText(data);
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_work);

        tvResult = findViewById(R.id.tv_result);

        IntentFilter filter = new IntentFilter(BroadcastConstants.ACTION_UPDATE_UI);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            registerReceiver(uiReceiver, filter, Context.RECEIVER_NOT_EXPORTED);
        } else {
            registerReceiver(uiReceiver, filter);
        }

        startService(new Intent(this, MyService.class));
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(uiReceiver);
    }
}

二、Fragment 与 Activity 通信(双向)

1、Fragment
xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#EEEEEE"
    android:orientation="vertical"
    android:padding="16dp">

    <TextView
        android:id="@+id/tv_fragment_msg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="12dp"
        android:text="Fragment 收到 Activity 的消息:无"
        android:textSize="16sp" />

    <Button
        android:id="@+id/btn_send_to_activity"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Fragment 发消息给 Activity" />
</LinearLayout>
java 复制代码
public class ChildFragment extends Fragment {

    private TextView tvFragmentMsg;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater,
                             @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_child, container, false);
        tvFragmentMsg = view.findViewById(R.id.tv_fragment_msg);

        view.findViewById(R.id.btn_send_to_activity).setOnClickListener(v -> {
            Intent intent = new Intent(ParentActivity.ACTION_FROM_FRAGMENT);
            intent.putExtra(ParentActivity.EXTRA_MSG_FROM_FRAGMENT, "你好,我是 Fragment");
            LocalBroadcastManager.getInstance(requireContext()).sendBroadcast(intent);
        });

        return view;
    }

    private final BroadcastReceiver activityReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (ParentActivity.ACTION_FROM_ACTIVITY.equals(intent.getAction())) {
                String msg = intent.getStringExtra(ParentActivity.EXTRA_MSG_FROM_ACTIVITY);
                tvFragmentMsg.setText("Fragment 收到 Activity 的消息:" + msg);
            }
        }
    };

    @Override
    public void onStart() {
        super.onStart();

        // 注册接收 Activity 的广播
        IntentFilter filter = new IntentFilter(ParentActivity.ACTION_FROM_ACTIVITY);
        LocalBroadcastManager.getInstance(requireContext()).registerReceiver(activityReceiver, filter);
    }

    @Override
    public void onStop() {
        super.onStop();

        // 注销接收 Activity 的广播
        LocalBroadcastManager.getInstance(requireContext()).unregisterReceiver(activityReceiver);
    }
}
2、Activity
xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <TextView
        android:id="@+id/tv_activity_msg"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingBottom="12dp"
        android:text="Activity 收到 Fragment 的消息:无"
        android:textSize="16sp" />

    <Button
        android:id="@+id/btn_send_to_fragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Activity 发消息给 Fragment" />

    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginTop="16dp"
        android:layout_weight="1" />
</LinearLayout>
java 复制代码
public class ParentActivity extends AppCompatActivity {

    // Activity -> Fragment 的广播
    public static final String ACTION_FROM_ACTIVITY = "com.example.ACTION_FROM_ACTIVITY";
    public static final String EXTRA_MSG_FROM_ACTIVITY = "extra_msg_from_activity";

    // Fragment -> Activity 的广播
    public static final String ACTION_FROM_FRAGMENT = "com.example.ACTION_FROM_FRAGMENT";
    public static final String EXTRA_MSG_FROM_FRAGMENT = "extra_msg_from_fragment";

    private TextView tvActivityMsg;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_parent);

        tvActivityMsg = findViewById(R.id.tv_activity_msg);

        findViewById(R.id.btn_send_to_fragment).setOnClickListener(v -> {
            Intent intent = new Intent(ACTION_FROM_ACTIVITY);
            intent.putExtra(EXTRA_MSG_FROM_ACTIVITY, "你好,我是 Activity");
            LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
        });

        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.container, new ChildFragment())
                    .commit();
        }
    }

    private final BroadcastReceiver fragmentReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (ACTION_FROM_FRAGMENT.equals(intent.getAction())) {
                String msg = intent.getStringExtra(EXTRA_MSG_FROM_FRAGMENT);
                tvActivityMsg.setText("Activity 收到 Fragment 的消息:" + msg);
            }
        }
    };

    @Override
    protected void onStart() {
        super.onStart();

        // 注册接收 Fragment 的广播
        IntentFilter filter = new IntentFilter(ACTION_FROM_FRAGMENT);
        LocalBroadcastManager.getInstance(this).registerReceiver(fragmentReceiver, filter);
    }

    @Override
    protected void onStop() {
        super.onStop();

        // 注销接收 Fragment 的广播
        LocalBroadcastManager.getInstance(this).unregisterReceiver(fragmentReceiver);
    }
}
相关推荐
wuminyu2 小时前
JVM规范学习总结:解释器与JIT编译器如何处理JVM字节码
java·linux·c语言·jvm·c++
txxzjmzlh2 小时前
SpringBoot 配置⽂件
java·spring boot·spring
小徐不徐说2 小时前
序列化与反序列化:把 C++ 对象可靠地保存下来
开发语言·数据库·c++·php
ragnwang2 小时前
Notes: Python pybind11 import C++ module
开发语言·c++·python
Wang's Blog2 小时前
Java 项目实战: 交友项目 - 搜索附近的功能概述和分析
java·开发语言·交友
骑着蜗牛撵大象3272 小时前
大模型 Agent 的沙箱护栏:gVisor 隔离、出口白名单与审计闭环
java·开发语言·jvm·安全·agent沙箱·gvisor·microvm
独泪了无痕3 小时前
Hutool之LocalDateTimeUtil:让时间间隔操作如虎添翼
java
Dxy12393102163 小时前
JS DES 加密详解
开发语言·javascript·arcgis
充值内卷4 小时前
我给桌面加了个鱼缸:C++ 写后端,WebView2 里养一座 Three.js 小岛
开发语言·javascript·c++
云和数据.ChenGuang4 小时前
深入解析 Python 的 dir():从用法到 CPython 源码实现
开发语言·人工智能·python·langchain