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

点击通知启动App崩溃:Fragment加载失败问题求助

问题:点击通知启动App崩溃,报错InflateException

我给App实现了新的事件通知功能,但点击通知启动App时发生崩溃,报错信息如下:

Process: it.breakingbad.crimegoaway, PID: 13239
java.lang.RuntimeException: Unable to start activity ComponentInfo{it.breakingbad.crimegoaway/it.breakingbad.crimegoaway.NavBarActivity}: android.view.InflateException: Binary XML file line #15 in it.breakingbad.crimegoaway:layout/activity_nav_bar: Binary XML file line #19 in it.breakingbad.crimegoaway:layout/content_nav_bar: Error inflating class fragment
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3520)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3692)
at android.app.ActivityThread.handleRelaunchActivityInner(ActivityThread.java:5580)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:5486)
at android.app.servertransaction.ActivityRelaunchItem.execute(ActivityRelaunchItem.java:69)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)

我怀疑问题出在NavBarActivity的onCreate方法中ActivityNavBarBinding.inflate(getLayoutInflater());这一行,以下是相关代码:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);

    try {
        binding = ActivityNavBarBinding.inflate(getLayoutInflater());
        // ... rest of body of onCreateView() ...
    } catch (Exception e) {
        Log.e("TAG", "onCreateView", e);
    }


    setContentView(binding.getRoot());

    setSupportActionBar(binding.appBarNavBar.toolbar);

    DrawerLayout drawer = binding.drawerLayout;
    NavigationView navigationView = binding.navView;
    View headerView = navigationView.getHeaderView(0);

    // Get Username and Email TextViews
    TextView userName = headerView.findViewById(R.id.nav_username);
    TextView userEmail = headerView.findViewById(R.id.nav_email);

    // set user name and email
    userName.setText("Username");
    Users.writeUsernameNavBar(userName);
    userEmail.setText(Users.getCurrentUser().getCurrentUser().getEmail());

    // Passing each menu ID as a set of Ids because each
    // menu should be considered as top level destinations.
    mAppBarConfiguration = new AppBarConfiguration.Builder(
            R.id.nav_home, R.id.nav_add_alert, R.id.nav_profile, R.id.nav_view_alerts, R.id.nav_my_alerts, R.id.nav_exit)
            .setOpenableLayout(drawer)
            .build();
    NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_nav_bar);
    NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
    NavigationUI.setupWithNavController(navigationView, navController);

    //work manager declaration if not present
    if(getIntent().getExtras() == null) {

        WorkManager.getInstance(getApplicationContext()).cancelAllWorkByTag(TAG_ALERTS);

        WorkRequest workAlertRequest = new PeriodicWorkRequest.Builder(AlertCheckerWorker.class, 4, TimeUnit.MINUTES)
                /*.setInitialDelay(3, TimeUnit.MINUTES)*/
                .addTag(TAG_ALERTS).build();
        WorkManager.getInstance(getApplicationContext()).enqueue(workAlertRequest);

        WorkManager.getInstance(getApplicationContext()).cancelAllWorkByTag(TAG_COMMENTS);

        WorkRequest workCommentRequest = new PeriodicWorkRequest.Builder(CommentCheckerWorker.class, 4, TimeUnit.MINUTES)
                /*.setInitialDelay(3, TimeUnit.MINUTES)*/
                .addTag(TAG_COMMENTS).build();
        WorkManager.getInstance(getApplicationContext()).enqueue(workCommentRequest);

    }

    //used for notification "re-routing"
    if(getIntent().getExtras() != null){
        Bundle bundle = getIntent().getExtras();
        if(bundle.getParcelable("alert") != null) {
            Alert alert = bundle.getParcelable("alert");

            DetailAlertFragment fragment_alert = new DetailAlertFragment();
            fragment_alert.setArguments(bundle);
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            transaction.add(R.id.nav_host_fragment_content_nav_bar, fragment_alert);
            transaction.commit();
        }
    }
}

通知创建代码

Intent resultIntent = new Intent(getApplicationContext(), NavBarActivity.class);
Bundle bundle = new Bundle();
bundle.putParcelable("alert", tempAlert);
resultIntent.putExtras(bundle);
//resultIntent.putExtra("alert", tempAlert);

Log.d("AlertCheckerWorker", "doWork: " + tempAlert.toString());
// Create the TaskStackBuilder and add the intent, which inflates the back stack
TaskStackBuilder stackBuilder = TaskStackBuilder.create(getApplicationContext());
stackBuilder.addNextIntentWithParentStack(resultIntent);
// Get the PendingIntent containing the entire back stack
int notificationId = (int) (System.currentTimeMillis() + new Random().nextInt());

PendingIntent resultPendingIntent =
        stackBuilder.getPendingIntent(notificationId,
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT);

Notification notification = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID)
        .setSmallIcon(R.drawable.category_crime)
        .setContentTitle("Alert Title: " + tempAlert.getTitle())
        .setContentText("Description: " + tempAlert.getDescription())
        .setContentIntent(resultPendingIntent)
        .setAutoCancel(true)
        .setDefaults(Notification.DEFAULT_ALL)
        .setPriority(NotificationCompat.PRIORITY_HIGH)
        .build();
notificationManager.notify(notificationId, notification);

DetailAlertFragment接收数据代码

alert = getArguments().getParcelable("alert");

//GraphicTools.showToast(getContext(),alert.toString());

alertTitleTextView.setText(alert.getTitle());

alertAddCommentImageButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        if(alertAddCommentEditText.getText().toString().length()>0){
            Comment comment=new Comment(alertAddCommentEditText.getText().toString(), Timestamp.now(), FirebaseAuth.getInstance().getCurrentUser().getUid());
            Comments.addCommentInFirestore(alert.getDocumentId(),comment);
            alertAddCommentEditText.setText("");
        }else {
            alertAddCommentEditText.setError("Add a comment");
        }
    }
});

alertDescriptionTextView.setText(alert.getDescription());

应用架构图


解决方案

核心问题分析

崩溃的直接原因是尝试向导航组件的宿主容器(R.id.nav_host_fragment_content_nav_bar)添加Fragment,该容器是Navigation Component专用的,只能由NavController管理Fragment切换,手动调用FragmentTransaction.add()会破坏导航栈结构,触发布局膨胀异常。你怀疑的ActivityNavBarBinding.inflate()并不是问题根源,真正触发点是通知跳转后的Fragment事务代码。

修复步骤

  1. 移除手动添加Fragment的代码
    删除NavBarActivity中通知处理块里的以下代码:

    DetailAlertFragment fragment_alert = new DetailAlertFragment();
    fragment_alert.setArguments(bundle);
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.add(R.id.nav_host_fragment_content_nav_bar, fragment_alert);
    transaction.commit();
    
  2. 使用Navigation Component深层链接跳转

    • 第一步:给DetailAlertFragment配置深层链接
      打开导航XML文件(如nav_graph.xml),给目标Fragment添加深层链接配置:

      <fragment
          android:id="@+id/detailAlertFragment"
          android:name="it.breakingbad.crimegoaway.DetailAlertFragment"
          android:label="DetailAlertFragment">
          <argument
              android:name="alert"
              app:argType="it.breakingbad.crimegoaway.Alert" />
          <deepLink
              android:id="@+id/deepLink_detailAlert"
              app:uri="app://crimegoaway/alert" />
      </fragment>
      
    • 第二步:修改通知Intent为深层链接形式
      替换通知创建代码中的Intent部分:

      // 创建深层链接Intent
      Intent resultIntent = new Intent(getApplicationContext(), NavBarActivity.class);
      // 传递Parcelable参数
      resultIntent.putExtra("alert", tempAlert);
      // 标记为导航跳转Intent
      resultIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
      
      // 保持TaskStackBuilder和PendingIntent代码不变
      TaskStackBuilder stackBuilder = TaskStackBuilder.create(getApplicationContext());
      stackBuilder.addNextIntentWithParentStack(resultIntent);
      int notificationId = (int) (System.currentTimeMillis() + new Random().nextInt());
      
      PendingIntent resultPendingIntent =
              stackBuilder.getPendingIntent(notificationId,
                      PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT);
      
    • 第三步:通过NavController处理跳转
      在NavBarActivity的通知处理块中,改用NavController跳转:

      if(getIntent().getExtras() != null){
          Bundle bundle = getIntent().getExtras();
          if(bundle.getParcelable("alert") != null) {
              NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_nav_bar);
              // 跳转到DetailAlertFragment并传递参数
              navController.navigate(R.id.detailAlertFragment, bundle);
          }
      }
      
    • 第四步:Fragment中安全接收参数
      推荐使用Safe Args(需在gradle中配置),也可以保留原代码但增加判空:

      // Safe Args方式(推荐)
      DetailAlertFragmentArgs args = DetailAlertFragmentArgs.fromBundle(getArguments());
      Alert alert = args.getAlert();
      
      // 普通方式(增加判空)
      Alert alert = getArguments().getParcelable("alert");
      if (alert == null) {
          getActivity().onBackPressed();
          return;
      }
      alertTitleTextView.setText(alert.getTitle());
      // ... 其他逻辑
      
  3. 额外优化
    现有代码中通过getIntent().getExtras() != null跳过WorkManager初始化的逻辑可以保留,避免App后台唤醒时重复创建任务。

修复原理

Navigation Component的宿主容器由框架统一管理导航栈,手动操作Fragment事务会导致框架状态混乱,引发布局异常。使用NavController跳转符合组件化规范,框架会自动处理Fragment的切换和栈管理,同时保证参数传递的安全性。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 04:16:10