AsyncTask的OnPostExecute()中的NPE

时间:2016-07-06 01:03:35

标签: android android-asynctask nullpointerexception

我正在尝试通过WHTTP与远程设备通信。我发送请求,设备响应。它并不总是立即响应,这就是我使用AsyncTask的原因。

这里有一些修剪过的代码可以更好地解释:

private class CameraSettings extends AsyncTask<AvailableCameraSettings, Void, AvailableCameraSettings> {
    private final String INNER_TAG = CameraSettings.class.getSimpleName();
    AvailableCameraSettings availableCameraSettings = new AvailableCameraSettings();


    @Override
    protected void onPostExecute(AvailableCameraSettings availableCameraSettings) {
        if(availableCameraSettings==null){
            Log.e(INNER_TAG, "NULL");
            return;
        }
        if (availableCameraSettings.getSetting().equals(SettingType.APERTURE) ) {
            apertureSettings = availableCameraSettings;
            ArrayAdapter<String> apertureAdapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_spinner_item);
            apertureAdapter.addAll(apertureSettings.getAvailableSettings());

            apertureSpinner.setAdapter(apertureAdapter);
            apertureSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                    String itemAtPosition = ((String) parent.getItemAtPosition(position));
                    mCameraIO.setAperture(itemAtPosition);
                }

                @Override
                public void onNothingSelected(AdapterView<?> parent) {

                }
            });
            apertureSpinner.setEnabled(true);
        } else if (availableCameraSettings.getSetting().equals(SettingType.ISO)) {
            isoSettings = availableCameraSettings;
            ArrayAdapter<String> isoSpeedAdapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_spinner_item);
            isoSpeedAdapter.addAll(isoSettings.getAvailableSettings());
            isoSpinner.setAdapter(isoSpeedAdapter);
            isoSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                @Override
                public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                    String itemAtPosition = ((String) parent.getItemAtPosition(position));
                    mCameraIO.setIsoSpeed(itemAtPosition);
                }

                @Override
                public void onNothingSelected(AdapterView<?> parent) {

                }
            });
            isoSpinner.setEnabled(true);

        }
    }

    @Override
    protected AvailableCameraSettings doInBackground(AvailableCameraSettings... params) {
        AvailableCameraSettings parameter = params[0];
        if (parameter != null) {
            Log.d(INNER_TAG, "***** Entered doInBackground method for setting " + parameter.getSetting().getName());
        }else{
            return null;
        }

        if (parameter.getSetting().equals(SettingType.APERTURE)) {
            mCameraIO.getApertures(new CameraListener() {
                @Override
                public void onResult(JSONArray response) {
                    if (response == null) {
                        Log.d(INNER_TAG, " Response is Null");
                        return;
                    }
                    try {
                        Log.d(INNER_TAG, "Response is: " + response.toString(4));
                        extractAvailableSettings(response, apertureSettings);
                    } catch (JSONException e) {
                        Log.e(TAG, e.getMessage());
                    }
                }

                @Override
                public void onError(CameraIO.ResponseCode responseCode, String responseMsg) {

                }
            });
            return apertureSettings;
        } else if (parameter.getSetting().equals(SettingType.ISO)) {
            mCameraIO.getIsoSpeedRates(new CameraListener() {
                @Override
                public void onResult(JSONArray response) {
                    if (response == null) {
                        Log.d(INNER_TAG, " Response is Null");
                        return;
                    }
                    try {
                        Log.d(INNER_TAG, "Response is: " + response.toString(4));
                        extractAvailableSettings(response, isoSettings);
                    } catch (JSONException e) {
                        Log.e(TAG, e.getMessage());
                    }
                }

                @Override
                public void onError(CameraIO.ResponseCode responseCode, String responseMsg) {

                }
            });
        }

        return null;
    }

}

产生的错误是:

  java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object[] java.util.Collection.toArray()' on a null object reference
                                                                             at java.util.ArrayList.addAll(ArrayList.java:188)
                                                                             at android.widget.ArrayAdapter.addAll(ArrayAdapter.java:210)
                                                                             at com.thibaudperso.sonycamera.timelapse.fragments.CameraSettingsFragment$CameraSettings.onPostExecute(CameraSettingsFragment.java:311)
                                                                             at com.thibaudperso.sonycamera.timelapse.fragments.CameraSettingsFragment$CameraSettings.onPostExecute(CameraSettingsFragment.java:297)
                                                                             at android.os.AsyncTask.finish(AsyncTask.java:651)
                                                                             at android.os.AsyncTask.access$500(AsyncTask.java:180)
                                                                             at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:668)
                                                                             at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                             at android.os.Looper.loop(Looper.java:148)
                                                                             at android.app.ActivityThread.main(ActivityThread.java:5468)
                                                                             at java.lang.reflect.Method.invoke(Native Method)
                                                                             at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

第311行是:

     apertureAdapter.addAll(apertureSettings.getAvailableSettings());   

我理解null List<String>到达那里,但我不明白为什么doInBackground()不等到它得到响应,然后返回新填充的对象。

1 个答案:

答案 0 :(得分:0)

对getApertures()和getIsoSpeedRates()的调用会收回回调(CameraListener),这意味着 已经等待 响应而无需使用一个AsyncTask。

这种情况发生的原因是它在 doInBackground完成后进入onResponse ,因为它本质上是另一个异步任务 ,从你的CameraSettings AsyncTask调用。

我建议完全删除AsyncTask,并创建类似的方法。请注意,updateAdapter的来电是从onResult调用的 - 因为此时您确实拥有了结果。 onResult基本上与onPostExecute的{​​{1}}相同,因此您需要在那里处理您的功能。

AsyncTask

然后添加如下方法。它与public void getCameraSettings(AvailableCameraSettings parameter) { if (parameter != null) { Log.d(INNER_TAG, "***** Entered doInBackground method for setting " + parameter.getSetting().getName()); }else{ return null; } if (parameter.getSetting().equals(SettingType.APERTURE)) { mCameraIO.getApertures(new CameraListener() { @Override public void onResult(JSONArray response) { if (response == null) { Log.d(INNER_TAG, " Response is Null"); return; } try { Log.d(INNER_TAG, "Response is: " + response.toString(4)); extractAvailableSettings(response, apertureSettings); updateAdapter(SettingType.APERTURE); } catch (JSONException e) { Log.e(TAG, e.getMessage()); } } @Override public void onError(CameraIO.ResponseCode responseCode, String responseMsg) { } }); return apertureSettings; } else if (parameter.getSetting().equals(SettingType.ISO)) { mCameraIO.getIsoSpeedRates(new CameraListener() { @Override public void onResult(JSONArray response) { if (response == null) { Log.d(INNER_TAG, " Response is Null"); return; } try { Log.d(INNER_TAG, "Response is: " + response.toString(4)); extractAvailableSettings(response, isoSettings); updateAdapter(SettingType.ISO); } catch (JSONException e) { Log.e(TAG, e.getMessage()); } } @Override public void onError(CameraIO.ResponseCode responseCode, String responseMsg) { } }); } return null; } 中的内容基本相同。看起来onPostExecuteisoSettings是成员变量,所以我相信您可以访问此处,但如果没有,请将它们添加为要传递给此方法的参数。

apertureSettings

注意:如果有充分的理由我错过了 使用AsyncTask - 你可以通过简单地调用你的方式来实现同样的目的来自protected void updateAdapter(String settingType) { if(availableCameraSettings==null){ Log.e(INNER_TAG, "NULL"); return; } if (settingType.equals(SettingType.APERTURE) ) { apertureSettings = availableCameraSettings; ArrayAdapter<String> apertureAdapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_spinner_item); apertureAdapter.addAll(apertureSettings.getAvailableSettings()); apertureSpinner.setAdapter(apertureAdapter); apertureSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { String itemAtPosition = ((String) parent.getItemAtPosition(position)); mCameraIO.setAperture(itemAtPosition); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); apertureSpinner.setEnabled(true); } else if (settingType.equals(SettingType.ISO)) { isoSettings = availableCameraSettings; ArrayAdapter<String> isoSpeedAdapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_spinner_item); isoSpeedAdapter.addAll(isoSettings.getAvailableSettings()); isoSpinner.setAdapter(isoSpeedAdapter); isoSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { String itemAtPosition = ((String) parent.getItemAtPosition(position)); mCameraIO.setIsoSpeed(itemAtPosition); } @Override public void onNothingSelected(AdapterView<?> parent) { } }); isoSpinner.setEnabled(true); } } updateAdapter内的新onResult方法,但我认为这是不必要的。