【问题标题】:Activities null pointer exception - How to debug活动空指针异常 - 如何调试
【发布时间】:2017-04-30 23:07:43
【问题描述】:

我有一个“SignUpActivity”,用户可以在其中登录我的应用程序,在极少数情况下(我只从 Fabric、Crashlytics 获得了一些),此特定活动在显示对话框之前完成。为了澄清这一点,请检查以下代码:

  private void register() {
    final ProgressDialog dialog = new ProgressDialog(this);
    dialog.setTitle("Registering");
    dialog.setMessage("Please wait..");
    if (dialogReady(dialog)) {
        dialog.show();
    }
    final AlertDialog alert = new AlertDialog.Builder(this)
            .setTitle("Error Occured")
            .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                }
            }).create();


    new ApiService(this).signUp(signUpModel).enqueue(new Callback<Void>() {
        @Override
        public void onResponse(Call<Void> call, Response<Void> response) {
            if (response.isSuccessful()) {
                //code
                finish();
            } else {
                if (dialogReady(dialog) && dialogReady(alert)) {
                    dialog.dismiss();
                    alert.setMessage(response.message());
                    alert.setMessage("Email already exists");
                    alert.show();
                }
            }
        }

        @Override
        public void onFailure(Call<Void> call, Throwable t) {
            if (dialogReady(dialog) && dialogReady(alert)) {
                dialog.dismiss();
                alert.setMessage("Check your internet connection");
                alert.show();
            }
        }
    });
}

我设法重现问题的方法是在开发人员选项中设置“不保留活动”。我设法通过使用我创建的 dialogReady 方法解决了这个问题:

 private boolean dialogReady(Dialog dialog) {
    return (dialog != null && !this.isFinishing());
}

但是,我真的很想知道为什么我的活动在代码中清楚地完成时,没有办法(或没有)在显示或关闭对话框之前完成。我检查了 Crashlytics,所有设备都有 30+% 的可用 RAM,并且活动本身非常简单,并且无论如何都不会使用太多内存。

引用 Activity 时也会弹出此问题。我有一个活动,我们称之为 A。A 打开一个活动 B,它使用来自 A 的静态变量,称之为 A.listener。当将它分配给活动 B 中该侦听器的新实例时,它会在 A 上引发空指针异常。我无法使用“不保留活动”重新创建它,这只发生在少数设备上。

我怎么可能想出一种方法来重现这个问题。我可以遵循一个很好的过程来调试这个罕见的问题。

谢谢。

编辑:我正在做的调用(新的 ApiService....)是一个异步 请求 *(使用改造)

【问题讨论】:

  • 你有没有想过使用AsyncTask?我认为建议在后台(与后端检查)和主线程中执行此类操作,您将显示 ProgressDialog。
  • @AndroidNFC 我正在使用改造的异步 request *,我正在做的调用 new ApiService.. 是异步的。
  • 但是我在你的代码中看不到你dismiss();你的对话或者我是盲人?因此,如果我认为正确,则过程是:您调用 register();首先,现在应该显示对话框。然后它应该启动后台线程以检查 SignUp 是否正确,如果成功则相应地关闭对话框(这部分我没有看到),只有在发生错误时才会关闭。所以你的 ProgressDialog 根本没有显示,对吗?
  • 是的,它正在显示,一切正常,使用我的问题中的方法(dialogReady),在调用之前检查,有一个 if(dialogready) dialog.show() 并且两者都有两次失败都被解雇了(即使成功了,我也删除了那个 bcz 它是一个大代码块,它是最后一行,所以那里也有一个解雇。我想要的是一种调试此类问题的方法。(Null活动指针异常)。如果您检查我的第二个示例,那是我无法调试和重新创建的示例
  • 您可以作为用户执行此操作吗?按住home键然后清内存?还有一些机器人确实会杀死活动,当他们认为他们运行的时间足够长时(尤其是在后台时)。并且要进入后台,例如,您可能只是接到一个电话,或者其他什么......很难说,Android 操作系统不能保证您的活动长时间保留在内存中,调试选项“不保留活动”模拟在某些设备上确实发生的最坏情况通常足以不容忽视。 (我记得还有一个……onConfigurationChanged 事情也可能造成严重破坏)

标签: android android-activity nullpointerexception reference


【解决方案1】:

@PampaZiya,我认为你必须使用Weak Reference Activity

活动的上下文存储在弱引用中,它将在弹出初始化中使用,因此在活动完成后活动的引用仍然存在,然后通过使用此引用不会发生崩溃。

您可以将活动的弱引用用作

WeakReference<Activity> weakReferenceActivity;

在活动的onCreate中初始化为

weakReferenceActivity = new WeakReference<Activity>(activity);

现在,使用这个引用来初始化进度条或进度对话框,你甚至可以在 AlertDialog 中使用。

final ProgressDialog dialog = new ProgressDialog(weakReferenceActivity );

final AlertDialog alert = new AlertDialog.Builder(weakReferenceActivity );

现在,每当您完成对话框时,请使用以下引用来关闭,这样就不会出现崩溃。

【讨论】:

  • 感谢您的回答。这是推荐的做事方式吗?或者你会称之为黑客?我想知道最佳的参考方式。这也适用于静态变量吗?在我的第二个示例中,我希望在活动 A 中引用静态变量“listener”。
  • @PampaZiya,我不知道你的问题是“你会称之为黑客吗?”。但我确信该引用将适用于静态变量。
  • 它似乎工作得很好。谢谢 !接受的答案。
  • @PampaZiya,欢迎您!
【解决方案2】:

当您想显示对话框时,首先检查活动 != null 和 !activity.isfinishing() ,例如:

if(!isFinishing())
{
    //show alert
}

【讨论】:

  • 谢谢,我已经包含了我用来执行此操作的方法的快照,其中包含您的解决方案,这是最佳的。但是,我的问题是我想要一种方法来调试此类问题并重新创建它们以进行进一步测试。
  • 对不起,我没接你
猜你喜欢
  • 2011-04-07
  • 2013-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多