Android: NullPointerException, what could be null

2019-07-19 08:27发布

From the Logcat:

11-26 06:43:40.643: E/AndroidRuntime(1163): FATAL EXCEPTION: AsyncTask #1
...
11-26 06:43:40.643: E/AndroidRuntime(1163): java.lang.RuntimeException: An error occured while executing doInBackground()
...
11-26 06:43:40.643: E/AndroidRuntime(1163): Caused by: java.lang.NullPointerException
...
11-26 06:43:40.643: E/AndroidRuntime(1163):     at com.example.mymobiletest.SearchTask.doInBackground(SearchTask.java:134)

Line number 134 is ed = (EditText) mainActivity.findViewById(R.id.mainSearchActivity_editTextSearch);. Now the execution of this line indicates that mainActivity (it is an instance of the main activity passed to the constructor of this AsyncTask) is not null. So what else could be null at this line, which is causing the NullPointerException?

@Override
protected String doInBackground(Void... voidParameters) {
    EditText ed=null;
    if (mainActivity!=null) {
        ed = (EditText) mainActivity.findViewById(R.id.mainSearchActivity_editTextSearch);
    } else {
        return "mainActivity is the Null culprit.";
    }

EDIT:- I do think that since I am not changing the UI in doInBackground() (but only reading from the UI), so this should not be a problem. But still I tried this in onPreExecute() since onPreExecute is executed in the UI thread, but I still get the NPE on the same statement.

@Override 
    protected void onPreExecute() {
        EditText ed=null;
        if (mainActivity!=null) {
            ed = (EditText) mainActivity.findViewById(R.id.mainSearchActivity_editTextSearch);//******NPE
        } else {
            Log.i(TAG, "mainActivity is the Null culprit.");
        }
        searchQuery = ed.getText().toString();
    }

4条回答
何必那么认真
2楼-- · 2019-07-19 08:42

You should make your task a static inner class unless you need to run multiple of these tasks at the same time. Then you should just separate the class entirely.

doInBackground performs a task, then returns the result to onPostExecute. This is the intended use for ASynctask's general use.

The difference is doInBackground runs in a completely separate thread via a background process. You have no guarantees when it will run or finish. It can't see the UI thread. onPostExecute however, runs on the UI thread.

What this implies is that your ASyncTask has no guarantee the same MainActivity will remain active. Activies get created and destroyed constantly for reasons not exposed to us programmers. Any change in orientation for example will destroy your MainActivity and recreate it, which means your passed reference is now empty regardless of where in the process it is. It could pass the first null check, then crash on the findViewById. You have NO guarantees what happens outside of onCreate().

If you make it an inner static class and call the edittext in onPostExecute it should work fine because the inner class will get reattached to the new activity instance.

查看更多
霸刀☆藐视天下
3楼-- · 2019-07-19 08:42

try this

    @Override 
    protected void onPreExecute() {
        EditText ed=null;
        if (mainActivity!=null) {
            ed = (EditText) mainActivity.findViewById(R.id.mainSearchActivity_editTextSearch);//******NPE
searchQuery = ed.getText().toString();
        } else {
            Log.i(TAG, "mainActivity is the Null culprit.");
        }

    }
查看更多
爷的心禁止访问
4楼-- · 2019-07-19 08:49

You are doing it

Completely Wrong

You are taking the reference of the UI components in background thread, You must not do that.All such references are taken in the onCreate() method of the activity.Whenever you will want to update these UI components,you can do it in the onPostExecute() of your AsyncTask

查看更多
闹够了就滚
5楼-- · 2019-07-19 08:51

As doInBackground() method runs on a different thread other than main thread, so you should not access UI elements in doInBackground() method. you should access UI elements either in OnProgress() or OnPostExcecute() method.

查看更多
登录 后发表回答