NetworkChangeListener中无法解析getSupportFragmentManager报错如何解决
问题根因
BroadcastReceiver本身不持有FragmentManager实例,getSupportFragmentManager()是AppCompatActivity专属方法,无法在广播接收器中直接调用- 新创建的
Messages实例还未附加到任何宿主,此时调用getChildFragmentManager()必然抛出未附加的异常 DialogFragment必须依附于FragmentActivity(或其子类)/ 已附加的 Fragment 才能展示,不能直接用应用上下文弹出- 补充注意:Android 7.0(API 24)及以上系统已经禁用了静态注册的
ConnectivityManager.CONNECTIVITY_ACTION广播接收,只能在Activity/Service中动态注册才能收到回调
正确解决方案
首先修正Messages类的构造方式,Android官方要求Fragment必须保留无参构造,否则页面重建时会崩溃,改造为Bundle传参:
public class Messages extends AppCompatDialogFragment { private static final String ARG_MESSAGE = "arg_message"; // 必须保留无参构造 public Messages() {} // 静态工厂方法传参,参数存入Bundle防止重建丢失 public static Messages newInstance(String message) { Messages fragment = new Messages(); Bundle args = new Bundle(); args.putString(ARG_MESSAGE, message); fragment.setArguments(args); return fragment; } @NonNull @Override public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { String message = getArguments() != null ? getArguments().getString(ARG_MESSAGE) : ""; AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle("Warning!!!") .setMessage(message) .setPositiveButton("ok", null); return builder.create(); } }
根据你的使用场景二选一即可:
方案1:仅当前活跃页面需要弹窗提示
如果你的NetworkChangeListener是在特定Activity里动态注册的,直接把Activity的FragmentManager传给广播即可:
public class NetworkChangeListener extends BroadcastReceiver { private static final String CONNECTION_WIFI_OFF ="WIFI OFF."; private FragmentManager fragmentManager; // 构造时传入宿主Activity的supportFragmentManager public NetworkChangeListener(FragmentManager fragmentManager) { this.fragmentManager = fragmentManager; } @Override public void onReceive(Context context, Intent intent) { if(ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())){ // 先判断状态,避免Activity销毁后弹窗崩溃 if (!fragmentManager.isStateSaved()) { Messages messages = Messages.newInstance(CONNECTION_WIFI_OFF); messages.show(fragmentManager,"messages"); } } } }
在注册广播的Activity中初始化即可:
// Activity onCreate内动态注册广播示例 NetworkChangeListener listener = new NetworkChangeListener(getSupportFragmentManager()); IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); registerReceiver(listener, filter); // 页面销毁时记得注销广播 @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(listener); }
方案2:全局任意场景都需要弹窗提示
如果是全局生效的广播,直接弹系统级AlertDialog即可,不需要依赖DialogFragment:
注意:该方案需要申请悬浮窗权限,Android 6.0以上需要动态申请
SYSTEM_ALERT_WINDOW权限
@Override public void onReceive(Context context, Intent intent) { if(ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())){ AlertDialog.Builder builder = new AlertDialog.Builder(context, androidx.appcompat.R.style.Theme_AppCompat_Dialog); builder.setTitle("Warning!!!") .setMessage(CONNECTION_WIFI_OFF) .setPositiveButton("ok", null) .setCancelable(true); AlertDialog dialog = builder.create(); // 设置全局弹窗类型 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); } else { dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); } dialog.show(); } }
内容的提问来源于stack exchange,提问作者Scripta14
相关产品推荐
相关产品推荐

