2016-07-06 118 views
0

我想通過WHTTP與遠程設備進行通信。我發送請求並且設備響應。它並不總是立即響應,這就是爲什麼我使用AsyncTask。NPE在AsyncTask的OnPostExecute()

下面是一些下調的代碼更好地解釋:

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()); 

我明白了一個空List<String>得到那裏,但我不明白爲什麼doInBackground()不等待,直到它得到噸他迴應,然後返回新填充的對象。

回答

0

到getApertures()和getIsoSpeedRates的調用()取在回調(CameraListener),這意味着它已經等待爲無需使用的AsyncTask的響應。

發生了什麼事是這種情況下,它變得到onResponse doInBackground完成後,因爲它本質上是另一個異步任務,從CameraSettings的AsyncTask被調用。

我建議完全刪除AsyncTask,並創建類似的方法以下。請注意,撥打updateAdapter的電話號碼是從onResult開始的 - 因爲此時您確實有結果。 onResult與的onPostExecute基本相同,所以您需要在那裏處理您的功能。

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; 
    } 

然後添加一個方法如下。它基本上與onPostExecute中的一樣。它看起來像isoSettingsapertureSettings是成員變量,所以我相信你可以在這裏訪問,但如果沒有,請將它們添加爲傳遞給此方法的參數。

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); 

    } 
} 

注:如果有我的思念,你爲使用的AsyncTask一個強有力的理由 - 你可以通過簡單地從onResult內內調用你的新updateAdapter方法達到同樣的doInBackground,但我認爲這是沒有必要的。


+0

仍然遇到空指針異常。如果我一步一步地執行代碼,我發現它從這裏[mCameraIO.getIsoSpeedRates(new CameraListener(){])直接跳轉到[return apertureSettings;]對象,但仍然沒有填充所需的數據。因爲doInBackground並沒有等待我的請求得到正確的響應 – Doru

+0

對於我需要從相機中獲取的每一個請求,thread.sleep(2000)都是以非常麻煩的方式工作的。代碼插入右上方返回availableSettings(iso,光圈等),所以我可以給它時間正確填充設置。我仍然在等待錯誤證明的決議。 – Doru

+1

是否有一個原因,你在AsyncTask這一點?我剛剛意識到你在doInBackground中使用了回調,這意味着你基本上在異步任務中執行另一個異步任務。如果您不需要使用AsyncTask,我將使用潛在的解決方案更新我的答案,因此在doInBackground完成後,「內部」可以隨時返回。我想你可以沒有AsyncTask。 –

相關問題