我无法从 AsyncTask 子类中的 doInBackground 方法获取数据
I can't fetch data from the doInBackground method in AsyncTask Subclass
我试图在我的应用程序中获取地震数据,但我的应用程序停止运行了。我的代码没有错误。甚至我添加了互联网许可。但是在获取数据时我认为会发生此错误。调试了没发现问题
Logcat:
2021-03-27 15:23:32.118 9533-9560/com.example.quakereportapp
E/eglCodecCommon: glUtilsParamSize: unknow param 0x000082da 2021-03-27
15:23:32.118 9533-9560/com.example.quakereportapp E/eglCodecCommon:
glUtilsParamSize: unknow param 0x000082da
ioctl_ping failed for device_type=5, ret=-1 2021-03-27 15:23:37.091
9533-9533/com.example.quakereportapp E/AndroidRuntime: FATAL
EXCEPTION: main
Process: com.example.quakereportapp, PID: 9533
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1513)
at com.android.org.conscrypt.Platform.blockGuardOnNetwork(Platform.java:415)
at com.android.org.conscrypt.ConscryptFileDescriptorSocket.shutdownAndFreeSslNative(ConscryptFileDescriptorSocket.java:1005)
at com.android.org.conscrypt.ConscryptFileDescriptorSocket.close(ConscryptFileDescriptorSocket.java:1000)
at com.android.okhttp.internal.Util.closeQuietly(Util.java:86)
at com.android.okhttp.internal.http.StreamAllocation.deallocate(StreamAllocation.java:256)
at com.android.okhttp.internal.http.StreamAllocation.connectionFailed(StreamAllocation.java:293)
at com.android.okhttp.internal.http.HttpEngine.close(HttpEngine.java:445)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:509)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:407)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:538)
at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getResponseCode(DelegatingHttpsURLConnection.java:105)
at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:26)
at com.example.quakereportapp.QueryUtils.makeHttpRequest(QueryUtils.java:82)
at com.example.quakereportapp.QueryUtils.fetchEarthquakeData(QueryUtils.java:35)
at com.example.quakereportapp.MainActivity.updateUi(MainActivity.java:27)
at com.example.quakereportapp.MainActivity.access0(MainActivity.java:14)
at com.example.quakereportapp.MainActivity$EarthQuakeAsyncTask.onPostExecute(MainActivity.java:58)
at com.example.quakereportapp.MainActivity$EarthQuakeAsyncTask.onPostExecute(MainActivity.java:33)
at android.os.AsyncTask.finish(AsyncTask.java:695)
at android.os.AsyncTask.access0(AsyncTask.java:180)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:712)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
我的 AsyncTask 子Class
private void updateUi(List<Earthquake> earthquakes) {
listView = findViewById(R.id.list_view);
ArrayList<Earthquake> earthquake = QueryUtils.fetchEarthquakeData(url);
EarthquakeAdapter earthquakeAdapterArrayAdapter = new EarthquakeAdapter(this, earthquake);
listView.setAdapter(earthquakeAdapterArrayAdapter);
}
private class EarthQuakeAsyncTask extends AsyncTask<String, Void, List<Earthquake>> {
@Override
protected ArrayList<Earthquake> doInBackground(String... urls) {
ArrayList<Earthquake> result = QueryUtils.fetchEarthquakeData(urls[0]);
return result;
}
@Override
protected void onPostExecute(List<Earthquake> result) {
updateUi(result);
}
我的 JSON 来自 QueryUtils 的提取器方法 Class
private static ArrayList<Earthquake> extractFeatureFromJson(String earthquakeJSON) {
// If the JSON string is empty or null, then return early.
if (TextUtils.isEmpty(earthquakeJSON)) {
return null;
}
ArrayList<Earthquake> earthquakes = new ArrayList<>();
try {
JSONObject baseJsonResponse = new JSONObject(earthquakeJSON);
JSONArray earthquakeArray = baseJsonResponse.getJSONArray("features");
for (int i = 0; i < earthquakeArray.length(); i++) {
//creates object from the given array
JSONObject currentEarthquake = earthquakeArray.getJSONObject(i);
//stores all the data from properties to properties object
JSONObject properties = currentEarthquake.getJSONObject("properties");
//here we assign the value of the specified keys from the properties
String magnitude = properties.getString("mag");
String location = properties.getString("place");
long time = properties.getLong("time");
//and now we create a new earthquake in every loop
Earthquake earthquake = new Earthquake(magnitude, location, time);
//finally we add it to the earthquakes list
earthquakes.add(earthquake);
}
} catch (JSONException e) {
Log.e(LOG_TAG, "Problem parsing the earthquake JSON results", e);
}
return earthquakes;
}
抛出异常是因为您从主线程调用 API。您的代码中的问题是您两次调用 API 。一次进入 doInBackground
,然后再次进入 updateUi
。
从 updateUi
中删除对 QueryUtils.fetchEarthquakeData(url)
的调用,它应该如下所示。
private void updateUi(List<Earthquake> earthquakes) {
listView = findViewById(R.id.list_view);
EarthquakeAdapter earthquakeAdapterArrayAdapter = new EarthquakeAdapter(this, earthquakes);
listView.setAdapter(earthquakeAdapterArrayAdapter);
}
我试图在我的应用程序中获取地震数据,但我的应用程序停止运行了。我的代码没有错误。甚至我添加了互联网许可。但是在获取数据时我认为会发生此错误。调试了没发现问题
Logcat:
2021-03-27 15:23:32.118 9533-9560/com.example.quakereportapp E/eglCodecCommon: glUtilsParamSize: unknow param 0x000082da 2021-03-27 15:23:32.118 9533-9560/com.example.quakereportapp E/eglCodecCommon: glUtilsParamSize: unknow param 0x000082da ioctl_ping failed for device_type=5, ret=-1 2021-03-27 15:23:37.091 9533-9533/com.example.quakereportapp E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.quakereportapp, PID: 9533 android.os.NetworkOnMainThreadException at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1513) at com.android.org.conscrypt.Platform.blockGuardOnNetwork(Platform.java:415) at com.android.org.conscrypt.ConscryptFileDescriptorSocket.shutdownAndFreeSslNative(ConscryptFileDescriptorSocket.java:1005) at com.android.org.conscrypt.ConscryptFileDescriptorSocket.close(ConscryptFileDescriptorSocket.java:1000) at com.android.okhttp.internal.Util.closeQuietly(Util.java:86) at com.android.okhttp.internal.http.StreamAllocation.deallocate(StreamAllocation.java:256) at com.android.okhttp.internal.http.StreamAllocation.connectionFailed(StreamAllocation.java:293) at com.android.okhttp.internal.http.HttpEngine.close(HttpEngine.java:445) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:509) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:407) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:538) at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getResponseCode(DelegatingHttpsURLConnection.java:105) at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:26) at com.example.quakereportapp.QueryUtils.makeHttpRequest(QueryUtils.java:82) at com.example.quakereportapp.QueryUtils.fetchEarthquakeData(QueryUtils.java:35) at com.example.quakereportapp.MainActivity.updateUi(MainActivity.java:27) at com.example.quakereportapp.MainActivity.access0(MainActivity.java:14) at com.example.quakereportapp.MainActivity$EarthQuakeAsyncTask.onPostExecute(MainActivity.java:58) at com.example.quakereportapp.MainActivity$EarthQuakeAsyncTask.onPostExecute(MainActivity.java:33) at android.os.AsyncTask.finish(AsyncTask.java:695) at android.os.AsyncTask.access0(AsyncTask.java:180) at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:712) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:6669) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
我的 AsyncTask 子Class
private void updateUi(List<Earthquake> earthquakes) {
listView = findViewById(R.id.list_view);
ArrayList<Earthquake> earthquake = QueryUtils.fetchEarthquakeData(url);
EarthquakeAdapter earthquakeAdapterArrayAdapter = new EarthquakeAdapter(this, earthquake);
listView.setAdapter(earthquakeAdapterArrayAdapter);
}
private class EarthQuakeAsyncTask extends AsyncTask<String, Void, List<Earthquake>> {
@Override
protected ArrayList<Earthquake> doInBackground(String... urls) {
ArrayList<Earthquake> result = QueryUtils.fetchEarthquakeData(urls[0]);
return result;
}
@Override
protected void onPostExecute(List<Earthquake> result) {
updateUi(result);
}
我的 JSON 来自 QueryUtils 的提取器方法 Class
private static ArrayList<Earthquake> extractFeatureFromJson(String earthquakeJSON) {
// If the JSON string is empty or null, then return early.
if (TextUtils.isEmpty(earthquakeJSON)) {
return null;
}
ArrayList<Earthquake> earthquakes = new ArrayList<>();
try {
JSONObject baseJsonResponse = new JSONObject(earthquakeJSON);
JSONArray earthquakeArray = baseJsonResponse.getJSONArray("features");
for (int i = 0; i < earthquakeArray.length(); i++) {
//creates object from the given array
JSONObject currentEarthquake = earthquakeArray.getJSONObject(i);
//stores all the data from properties to properties object
JSONObject properties = currentEarthquake.getJSONObject("properties");
//here we assign the value of the specified keys from the properties
String magnitude = properties.getString("mag");
String location = properties.getString("place");
long time = properties.getLong("time");
//and now we create a new earthquake in every loop
Earthquake earthquake = new Earthquake(magnitude, location, time);
//finally we add it to the earthquakes list
earthquakes.add(earthquake);
}
} catch (JSONException e) {
Log.e(LOG_TAG, "Problem parsing the earthquake JSON results", e);
}
return earthquakes;
}
抛出异常是因为您从主线程调用 API。您的代码中的问题是您两次调用 API 。一次进入 doInBackground
,然后再次进入 updateUi
。
从 updateUi
中删除对 QueryUtils.fetchEarthquakeData(url)
的调用,它应该如下所示。
private void updateUi(List<Earthquake> earthquakes) {
listView = findViewById(R.id.list_view);
EarthquakeAdapter earthquakeAdapterArrayAdapter = new EarthquakeAdapter(this, earthquakes);
listView.setAdapter(earthquakeAdapterArrayAdapter);
}