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

网络状态变化时切换图片:BroadcastReceiver方案无效求助

我已经试过论坛上找到的多种解决方案,但都对我的情况无效。我的需求是在网络连接开启或关闭时切换界面上的图片,因此编写了一个继承自BroadcastReceiver的ConnectivityReceiver类,本希望它能在网络状态变化时通知主类,但目前没能正常工作。我的代码片段如下:

public class ConnectivityReceiver extends BroadcastReceiver { 
    public static ConnectivityReceiverListener connectivityReceiverListener; 
    public ConnectivityReceiver() {
        super();
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        // 这里本来要处理网络状态并通知主类,但好像没触发或者没传过去
    }

    public interface ConnectivityReceiverListener {
        void onNetworkConnectionChanged(boolean isConnected);
    }
}

下面是我总结的几个能解决这个问题的关键点,都是实际踩坑后验证有效的:

解决ConnectivityReceiver无法通知主类的问题

1. 别用静态注册,必须动态注册(Android 7.0+限制)

从Android 7.0开始,系统就禁止静态注册CONNECTIVITY_ACTION广播了,所以如果你的Receiver是在AndroidManifest里静态注册的,肯定收不到通知。正确的做法是在主Activity的onResume()里动态注册,onPause()里注销,避免内存泄漏:

@Override
protected void onResume() {
    super.onResume();
    IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
    registerReceiver(new ConnectivityReceiver(), filter);
}

@Override
protected void onPause() {
    super.onPause();
    unregisterReceiver(new ConnectivityReceiver());
}

另外,别忘了在Manifest里添加必要的权限:

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

2. 确保回调接口正确绑定和调用

你的Receiver里定义了ConnectivityReceiverListener,但得让主类实现这个接口,并且把实例传给Receiver的静态变量,同时在onReceive里正确触发回调:

先补全Receiver的onReceive方法:

@Override
public void onReceive(Context context, Intent intent) {
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();

    // 关键:调用回调通知主类
    if (connectivityReceiverListener != null) {
        connectivityReceiverListener.onNetworkConnectionChanged(isConnected);
    }
}

然后主Activity要实现接口并绑定Listener:

public class MainActivity extends AppCompatActivity implements ConnectivityReceiver.ConnectivityReceiverListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 绑定Listener,让Receiver能找到主类
        ConnectivityReceiver.connectivityReceiverListener = this;
    }

    @Override
    public void onNetworkConnectionChanged(boolean isConnected) {
        // 在这里完成图片切换,注意要在主线程操作
        ImageView networkImg = findViewById(R.id.iv_network_status);
        if (isConnected) {
            networkImg.setImageResource(R.drawable.ic_network_connected);
        } else {
            networkImg.setImageResource(R.drawable.ic_network_disconnected);
        }
    }

    // 别忘了前面的动态注册/注销代码
}

3. 高版本系统推荐用NetworkCallback替代BroadcastReceiver

Android 10及以上,CONNECTIVITY_ACTION广播的触发逻辑有很多限制,官方更推荐用ConnectivityManager.NetworkCallback来监听网络状态,这个方式更稳定:

private ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
    @Override
    public void onAvailable(Network network) {
        super.onAvailable(network);
        // 网络连接成功,切图
        runOnUiThread(() -> {
            ImageView img = findViewById(R.id.iv_network_status);
            img.setImageResource(R.drawable.ic_network_connected);
        });
    }

    @Override
    public void onLost(Network network) {
        super.onLost(network);
        // 网络断开,切图
        runOnUiThread(() -> {
            ImageView img = findViewById(R.id.iv_network_status);
            img.setImageResource(R.drawable.ic_network_disconnected);
        });
    }
};

// 注册回调
@Override
protected void onResume() {
    super.onResume();
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    cm.registerNetworkCallback(
            new NetworkRequest.Builder().build(),
            networkCallback
    );
}

// 注销回调
@Override
protected void onPause() {
    super.onPause();
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    cm.unregisterNetworkCallback(networkCallback);
}

这种方式不需要BroadcastReceiver,直接通过系统回调就能拿到网络状态变化,比广播更可靠。

4. 注意UI操作必须在主线程

不管用哪种方式,切换图片是UI操作,一定要确保在主线程执行。虽然onReceive默认是在主线程,但如果Receiver是单独进程的话就会出问题,所以保险起见,用runOnUiThread或者Handler把操作切到主线程,避免崩溃。

你可以对照这几点检查自己的代码,应该能解决Receiver无法通知主类的问题。

内容的提问来源于stack exchange,提问作者DeimosPhx

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 11:08:44