我正在尝试通过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()
不等到它得到响应,然后返回新填充的对象。
答案 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;
}
中的内容基本相同。看起来onPostExecute
和isoSettings
是成员变量,所以我相信您可以访问此处,但如果没有,请将它们添加为要传递给此方法的参数。
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
方法,但我认为这是不必要的。