【问题标题】:Quickly changing Bottom Navigation app crashes快速更改底部导航应用程序崩溃
【发布时间】:2019-02-05 07:53:58
【问题描述】:

我有带有片段的底部导航和用于 api 调用的改造

我调用loadFragment来切换片段如下

private boolean loadFragment(Fragment fragment) {
        //switching fragment
        if (fragment != null) {
            getSupportFragmentManager()
                    .beginTransaction()
                    .replace(R.id.fragment_container, fragment)
                    .commit();
            return true;
        }
        return false;
    }

问题是我的应用程序崩溃,如果我开始随机点击并快速更改片段,当我检查 logcat 时它在设置一些数据时显示 NPE。

我的 Fragment 由以下方法组成

 @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_current, container, false);
    unbinder = ButterKnife.bind(this, view);
    context = getActivity();
    callCategoryAPI();
    return view;
}

callCategory() 是单独控制器类中的 api 改造调用,并通过 interface 带回响应,然后设置数据。

所以我怀疑我的 API 返回响应(因为它是异步的)但是视图不可用,因为用户已经更改了片段(快速)所以视图为空。

我已经尝试过setuserVisibleHint 也尝试过阻止点击 1200 毫秒,还检查了我的片段视图是否已创建,如何阻止此崩溃?并使改造调用依赖于生命周期?

Logcat

在 com.example.CurrentFragment$1.onApiSuccess(CurrentFragment.java:82) 在 com.example.services.current_statement.CurrentStatementController$2.onResponse(CurrentStatementController.java:91) 在改造2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:70) 在 android.os.Handler.handleCallback(Handler.java:790) 在 android.os.Handler.dispatchMessage(Handler.java:99) 在 android.os.Looper.loop(Looper.java:171) 在 android.app.ActivityThread.main(ActivityThread.java:6606) 在 java.lang.reflect.Method.invoke(Method.java) 在 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:518) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)

--

致命异常:java.lang.NullPointerException:尝试调用 虚方法'void android.widget.TextView.setText(java.lang.CharSequence)' 为空 对象引用 在 com.example.fragment.statements.CurrentFragment$1.onApiSuccess(CurrentFragment.java:82) 在 com.example.services.current_statement.CurrentStatementController$2.onResponse(CurrentStatementController.java:91) 在改造2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:70) 在 android.os.Handler.handleCallback(Handler.java:790) 在 android.os.Handler.dispatchMessage(Handler.java:99) 在 android.os.Looper.loop(Looper.java:171) 在 android.app.ActivityThread.main(ActivityThread.java:6606) 在 java.lang.reflect.Method.invoke(Method.java) 在 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:518) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)

【问题讨论】:

  • 你真的想快速移动你的片段吗?
  • 我不想这样做,但这是一个我需要在尽快发布应用程序之前解决的错误
  • 请向我们展示完整的崩溃日志
  • 你的意思是说如果用户快速移动片段然后应用程序将崩溃。正确的。这就是你想要修复它的原因..
  • 完全是@UmangBurman

标签: android android-fragments retrofit bottomnavigationview


【解决方案1】:

这就是问题所在:

尝试在空对象引用上调用虚拟方法“void android.widget.TextView.setText(java.lang.CharSequence)”

您想将文本设置为 null 的文本视图。你应该首先检查你的 textview 不是这样的:

if (textview != null){
    textview.setText("mytext");
}

【讨论】:

  • 在这种情况下,他必须添加它以获得这么多的视图..我不推荐这样.. IMO
  • 它不只是 TextView 我在设置各种数据之后我不能添加 100 的检查对吗?
  • 问题是你为什么会得到NPE。从您的崩溃日志中可以清楚地看到为什么会发生 NPE...
【解决方案2】:

使用下面的这个库来阻止活动,直到网络操作完成。

Spot Dialog

这是我在之前向您展示的图片中用于我的应用程序的内容。

【讨论】:

  • 正如我已经说过的,我在每个 API 调用中都有ProgressDialog,但是当我尝试快速单击时,片段被替换并且我得到 NPE
  • 你使用过内置的 ProgressDialog 或任何库吗?
  • 安卓默认ProgressDialog
  • 不要使用它,因为它将被限制在它的视图中并且看起来也不好看。请参阅我编辑的答案。
  • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
【解决方案3】:

我可能会迟到,但我希望我也能帮助其他开发人员,因为我也遇到过这个问题。只需在 if-else 内的 onResponse 回调中使用 isAdded() 即可

例如:在您的 onResponse 回调中:

if (isAdded()){
  // success response
} else {
  if(isAdded()){
    // error response
  }
}

【讨论】:

  • 嘿,蒂米。您的代码有问题,elseif 条件相同,永远不会执行。也许你的意思是只使用 else 而不使用 if ?
  • 嗨,我是 android 的新手,但据我了解,如果你有前的代码,那是在 else 中。 Toast,由于单击垃圾邮件导航按钮调用多个片段并立即销毁,Toast 将获得 nullpointer 异常,现在在 else 内部您必须再次检查片段是否已添加以确保您不会获得 nullpointer 异常。干杯!
【解决方案4】:

在你的片段中设置

 if(activity != null && isAdded) {

  // perform your task

}

【讨论】:

    【解决方案5】:

    签入片段

    if(activity != null && isAdded){
    
     Perform your operation
    
    }
    

    【讨论】:

      【解决方案6】:

      在你的片段中设置

       if(getActivity() != null && isAdded) {
      
       //do your operation
      
      }
      

      【讨论】:

        【解决方案7】:

        代码用于 android 中的 kotlin:

        TextView?.text

        这里?表示不为空

        像上面那样使用它

        【讨论】:

          【解决方案8】:

          如果您快速更改导航抽屉菜单项,当前片段也会被新片段替换。 Android 可以删除在主线程中运行的任何正在进行的计算。但是,如果任何繁重的任务,如后台网络响应结果或具有片段引用的处理程序延迟任务都可以找到 null,因为片段已经分离或被新片段替换。

          因此,您只需检查一下,您的愿望片段是否仍然添加到活动中,然后再处理最近出现的响应数据。

              if(frag.isAdded()){
                  //lets process your delayed response data
              }
          

          【讨论】:

            猜你喜欢
            • 2019-11-25
            • 1970-01-01
            • 1970-01-01
            • 2016-10-27
            • 2014-07-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-05-05
            相关资源
            最近更新 更多