You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Fragment中向Broadcast Receiver传递类对象?

在Fragment中向Broadcast Receiver传递类对象的问题与解决方法

问题描述

我需要在Fragment中向Broadcast Receiver传递一个类对象,但直接在Receiver中new Fragment实例并调用其对象时,该对象始终为null。比如我实现了一个处理自定义Notification布局事件的Receiver类,除了record.pause()操作外其他功能都正常——Receiver中的MediaRecorder对象一直是null,但在录制音频的Sample_Fragment中该对象明明不为null,导致无法停止录制。

我的Receiver代码如下:

public class Sample_Receiver extends BroadcastReceiver {

    Sample_Fragment fragment = new Sample_Fragment();

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if ("pause".equalsIgnoreCase(action)) {
            record.pause();
        }
    }
}

问题原因

核心问题是在Receiver中new了一个全新的Sample_Fragment实例,这个实例和正在运行的、持有有效MediaRecorder对象的Fragment完全不是同一个,所以自然无法获取到已初始化的record对象。

解决方法

方法一:使用Fragment内部的BroadcastReceiver

直接在Sample_Fragment中定义内部BroadcastReceiver,这样Receiver可以直接访问Fragment中的成员变量(包括MediaRecorder对象),无需跨实例传递:

public class Sample_Fragment extends Fragment {
    private MediaRecorder record;
    private BroadcastReceiver sampleReceiver;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 初始化MediaRecorder
        record = new MediaRecorder();
        //... 其他初始化操作

        // 注册内部Receiver
        sampleReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if ("pause".equalsIgnoreCase(action)) {
                    if (record != null) {
                        record.pause();
                    }
                }
            }
        };
        IntentFilter filter = new IntentFilter("pause");
        requireContext().registerReceiver(sampleReceiver, filter);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // 记得注销Receiver,避免内存泄漏
        if (sampleReceiver != null) {
            requireContext().unregisterReceiver(sampleReceiver);
        }
    }
}

方法二:通过ViewModel共享状态

通过ViewModel在Fragment和Receiver之间共享录制状态和控制逻辑,Receiver可以通过ViewModel获取到当前有效的MediaRecorder实例:

public class RecordViewModel extends ViewModel {
    private MediaRecorder record;

    public void initRecorder() {
        record = new MediaRecorder();
        //... 初始化操作
    }

    public void pauseRecord() {
        if (record != null) {
            record.pause();
        }
    }
}

在Fragment中初始化ViewModel:

public class Sample_Fragment extends Fragment {
    private RecordViewModel viewModel;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        viewModel = new ViewModelProvider(requireActivity()).get(RecordViewModel.class);
        viewModel.initRecorder();
    }
}

在Receiver中获取ViewModel并调用方法:

public class Sample_Receiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if ("pause".equalsIgnoreCase(action)) {
            if (context instanceof Activity) {
                RecordViewModel viewModel = new ViewModelProvider((Activity) context).get(RecordViewModel.class);
                viewModel.pauseRecord();
            }
        }
    }
}

方法三:传递Parcelable封装对象(适用于独立Receiver)

如果必须使用独立的Receiver类,可以将录制相关状态封装成实现Parcelable接口的类,通过Intent传递给Receiver:

  1. 封装状态类:
public class RecordControlInfo implements Parcelable {
    // 可添加录制会话标识、状态等信息
    private String sessionId;

    protected RecordControlInfo(Parcel in) {
        sessionId = in.readString();
    }

    public RecordControlInfo(String sessionId) {
        this.sessionId = sessionId;
    }

    public static final Creator<RecordControlInfo> CREATOR = new Creator<RecordControlInfo>() {
        @Override
        public RecordControlInfo createFromParcel(Parcel in) {
            return new RecordControlInfo(in);
        }

        @Override
        public RecordControlInfo[] newArray(int size) {
            return new RecordControlInfo[size];
        }
    };

    public String getSessionId() {
        return sessionId;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(sessionId);
    }
}
  1. Fragment发送广播时传递:
String sessionId = "current_record_session";
Intent intent = new Intent("pause");
intent.putExtra("record_info", new RecordControlInfo(sessionId));
requireContext().sendBroadcast(intent);
  1. Receiver中接收并处理:
public class Sample_Receiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if ("pause".equalsIgnoreCase(action)) {
            RecordControlInfo info = intent.getParcelableExtra("record_info");
            // 根据sessionId获取对应的录制实例(比如通过全局单例、ViewModel等方式)
        }
    }
}

更新:我已经通过使用内部BroadcastReceiver的方式解决了这个问题。


内容的提问来源于stack exchange,提问作者A.G

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 03:54:30