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);
    }
}
相关推荐
阿俊-全栈开发1 小时前
LikeShop 单商户标准版商品管理二开:分类、SKU 规格与库存联动实现
android·likeshop·likeshop开源商城
Wang's Blog1 小时前
Java 项目实战: 交友项目 - 安装 Nacos 注册中心与 Dubbo 监控中心
java·dubbo·交友
前端 贾公子1 小时前
LangGraph == 图的状态(State)管理 (中)
开发语言·数据库·python
李福春1 小时前
斗破Google ADK Java苍穹-第2境斗者-凝旋筑基-Java环境
java·开发语言·gemini·llmagent·深圳同盟·腾讯云架构师技术同盟·adk java
霸道流氓气质1 小时前
LLM API密钥管理与轮换策略:Spring Vault动态密钥、熔断限流协同与多Provider路由的 Java 生产级实现
java·后端·spring
兔头?2 小时前
使用JDK21新特性虚拟线程时遇到的坑
java
老王爱玩车2 小时前
预处理详解
c语言·开发语言·学习
灯澜忆梦2 小时前
【Go Zap 日志库】#1 |快速上手 + 配置详解
开发语言·后端·golang