Android Java: 从另一个 class 调用的 AlertDialog 方法导致空指针异常

Android Java: AlertDialog method called from another class causes null pointer exception

我试图从另一个 class 调用一个方法,然后调用一个 AlertDialog 方法,我已经尝试了很多方法,但它总是导致空指针异常。调用 class 是 运行 一个 Web 服务器,我在 activity class 上有一个 RecyclerView 列表,其中包含被调用的方法。这是来自 activity class 和 AlertDialog:

的一些代码
public class ListClass extends AppCompatActivity {

    private WebSvr server;
    private static final int PORT = 8080;
    private androidx.appcompat.widget.Toolbar toolbar;
    private ListView lv;
    private CustomAdapter customAdapter;
    public ArrayList<EditModel> editModelArrayList;
    public static String[] newList = new String[20];

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_server_screen);
        toolbar = (androidx.appcompat.widget.Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        startWebServer();

        customAdapter = new CustomAdapter(this, editModelArrayList);
        lv.setAdapter(customAdapter);
    }

    public static boolean listUpdated;

    public void updateList() {
        listUpdated = false;
        Runnable r = new Runnable() {
            @Override
            public void run() {

                for (int i = 0; i < 20; i++) {
                    if (CustomAdapter.editModelArrayList.get(i).getEditTextValue() != "") {
                        newList[i] = CustomAdapter.editModelArrayList.get(i).getEditTextValue();
                    } else {
                        if (!showNotification) {

                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    showNullFieldNotification(); // <------------- CALLING THIS 
                                }
                            });
                            showNotification = true;
                        }
                    }
                }
                listUpdated = true;
            }
        };
        Thread thread = new Thread(r);
        thread.start();
    }

    boolean showNotification = false;

    public void showNullFieldNotification() {
        new AlertDialog.Builder(ListClass.this)
                .setTitle("Warning, some fields are empty")
                .setNegativeButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        dialogInterface.cancel();
                        showNotification = false;
                    }
                }).show();
    }

    public static boolean returnListUpdated() {
        return listUpdated;
    }

...

}

这是来自我的网络服务器的代码 class:

public class WebSvr extends NanoHTTPD {

    public ListClass ListClass = new ListClass();

    public WebSvr(int port){
        super(port);
    }

    @Override
    public Response serve(String uri, Method method,
                          Map<String, String> header,
                          Map<String, String> parameters,
                          Map<String, String> files) {


        ListClass.updateList(); // <--------------- THE METHOD CALLED

        while (!ListClass.returnListUpdated()) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        String strResponse = Arrays.toString(ListClass.returnString());

        return newFixedLengthResponse(strResponse);
    }
}

总是在这一行引起空指针异常:

new AlertDialog.Builder(ListClass.this)

以及在 ListClass 中调用该方法的位置:

showNullFieldNotification();

错误信息:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.espressif.iot_esptouch_demo, PID: 18217
    java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference
        at android.content.ContextWrapper.getApplicationInfo(ContextWrapper.java:152)
        at android.view.ContextThemeWrapper.getTheme(ContextThemeWrapper.java:157)
        at android.app.AlertDialog.resolveDialogTheme(AlertDialog.java:224)
        at android.app.AlertDialog$Builder.<init>(AlertDialog.java:454)
        at com.myProject.ListClass.showNullFieldNotification(ListClass.java:177)
        at com.myProject.ListClass.run(ListClass.java:193)
        at android.os.Handler.handleCallback(Handler.java:789)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6665)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:772)

如果我在 ListClass onCreate() 中调用 showNullFieldNotification() 或从选项菜单中调用它没有问题,但是当从 WebSvr class 中调用时它总是导致异常。

对于 AlertDialog 上的上下文,我尝试了 ListClass.thisgetApplicationContext()getBaseContext()... 我尝试在 [=31 中保存上下文=] as getApplicationContext() 并使用它。

我曾尝试使用 this 问题的解决方案来获取上下文,但这也不起作用。非常感谢任何帮助。

编辑:忘记提及我也曾尝试以这种方式构建警报:

public void showNullFieldNotification2() {
        AlertDialog.Builder alert = new AlertDialog.Builder(ListClass.this);
                alert.setTitle("Warning, some fields detected as being empty or having \"0\" as value");
                alert.setNegativeButton("OK", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        dialogInterface.cancel();
                        showNotification = false;
                    }
                });
                AlertDialog dialog = alert.create();
                dialog.show();
    }

您忘记创建警报对话框,所以它为空,而不是上下文

Android simple alert dialog

here in answer from Dan Bray 得到了解决方案。需要使用静态上下文。

由于您是从 activity 外部调用的,因此您需要将上下文保存在 activity class:

public static Context context;

并在 onCreate 内部:

context = this;

显示通知:

new Handler(Looper.getMainLooper()).post(new Runnable(){
            @Override
            public void run(){

                new AlertDialog.Builder(context)
                        .setTitle("Warning, some fields are empty")
                        .setNegativeButton("OK",new DialogInterface.OnClickListener(){
                            @Override
                            public void onClick(DialogInterface dialogInterface,int i){
                                dialogInterface.cancel();
                                showNotification=false;
                            }
                        }).show();

            }
        });

activityclass中调用的方法也必须是public static.