Android Studio中AsyncTask获取JSON,onPostExecute不执行问题求助
尝试从Pastebin的JSON文件获取数据并加载到ListView时,调用execute后onPreExecute正常执行,但onPostExecute完全没触发。
点击事件代码
public void onClick(View view) { ExtragereJSON extragereJSON = new ExtragereJSON() { ProgressDialog progressDialog; @Override protected void onPreExecute() { progressDialog = new ProgressDialog(Proba_Practica_Petrescu_Rares_Mihnea.this); progressDialog.setMessage("Please wait..."); progressDialog.show(); } @Override protected void onPostExecute(String s) { //progressDialog.setMessage("Done..."); //progressDialog.show(); progressDialog.cancel(); if (s != null) { listaInregistrari.addAll(this.listaRestaurante); // CustomAdapter adaptorNou = new CustomAdapter(getApplicationContext(), R.layout.listviewrestaurante_layout, // getLayoutInflater(), listaInregistrari); Log.d("AsyncTask", "onPostExecute: JSON extraction successful"); } else { // Handle the case where the JSON extraction failed // Log or display an error message Log.e("AsyncTask", "onPostExecute: Failed to extract JSON"); } } }; try { extragereJSON.execute(new URL("https://pastebin.com/raw/vVBcgK7H")); } catch (MalformedURLException e) { Log.e("URLValidationError", "Malformed URL: " + e.getMessage()); e.printStackTrace(); } catch (Exception e) { // Log or display a general error message Log.e("ExtractionError", "Failed to extract JSON: " + e.getMessage()); e.printStackTrace(); } }
ExtragereJSON类实现
public class ExtragereJSON extends AsyncTask<URL,Void,String> { public List<InregistrareRestaurant> listaRestaurante=new ArrayList<>(); @Override protected String doInBackground(URL... urls) { try { HttpURLConnection connection=(HttpURLConnection) urls[0].openConnection(); connection.setRequestMethod("GET"); InputStream inputStream=connection.getInputStream(); InputStreamReader isr=new InputStreamReader(inputStream); BufferedReader br=new BufferedReader(isr); String line=null; String rezultat=""; while((line=br.readLine())!=null) rezultat+=line; parsareJSON(rezultat); return rezultat; } catch (IOException e) { Log.e("AsyncTask", "Exception in doInBackground: " + e.getMessage()); return null; // Return null or an error message } } private void parsareJSON(String result){ if(result!=null){ try{ JSONObject obiect=new JSONObject(result); JSONArray restaurante = obiect.getJSONArray("restaurante"); for (int i = 0; i < restaurante.length(); i++) { JSONObject restaurant = restaurante.getJSONObject(i); int codRestaurant = restaurant.getInt("codRestaurant"); String numeRestaurant = restaurant.getString("numerestaurant"); int capacitate = restaurant.getInt("capacitate"); float venituri = (float) restaurant.getDouble("venituri"); String tipRestaurant = restaurant.getString("tipRestaurant"); InregistrareRestaurant ir = new InregistrareRestaurant(codRestaurant, numeRestaurant, capacitate, venituri, tipRestaurant); listaRestaurante.add(ir); } } catch (Exception e) { throw new RuntimeException(e); } } else { Log.e("parsareJSON","JSON este null"); } } }
问题原因分析
核心问题出在parsareJSON方法的异常处理:当JSON解析过程中出现任何异常时,代码直接抛出RuntimeException,而这个异常没有在doInBackground中被捕获。AsyncTask的后台任务一旦遇到未捕获的异常,会直接终止,不会执行return语句,也就不会触发onPostExecute,而是会调用onCancelled方法(如果有重写的话)。
另外,网络请求的资源(HttpURLConnection、InputStream、BufferedReader)没有关闭,可能导致资源泄漏,但这不是onPostExecute不触发的直接原因。
解决步骤
修复JSON解析的异常处理
不要抛出RuntimeException,而是捕获异常后记录日志,确保doInBackground能正常返回结果:private void parsareJSON(String result){ if(result!=null){ try{ JSONObject obiect=new JSONObject(result); JSONArray restaurante = obiect.getJSONArray("restaurante"); for (int i = 0; i < restaurante.length(); i++) { JSONObject restaurant = restaurante.getJSONObject(i); int codRestaurant = restaurant.getInt("codRestaurant"); String numeRestaurant = restaurant.getString("numerestaurant"); int capacitate = restaurant.getInt("capacitate"); float venituri = (float) restaurant.getDouble("venituri"); String tipRestaurant = restaurant.getString("tipRestaurant"); InregistrareRestaurant ir = new InregistrareRestaurant(codRestaurant, numeRestaurant, capacitate, venituri, tipRestaurant); listaRestaurante.add(ir); } } catch (Exception e) { Log.e("parsareJSON", "JSON解析失败: " + e.getMessage()); e.printStackTrace(); // 可以选择清空列表,避免添加无效数据 listaRestaurante.clear(); } } else { Log.e("parsareJSON","JSON内容为空"); } }添加资源关闭逻辑
在doInBackground中使用try-with-resources或者手动关闭网络连接和流,防止资源泄漏:@Override protected String doInBackground(URL... urls) { HttpURLConnection connection = null; BufferedReader br = null; try { connection=(HttpURLConnection) urls[0].openConnection(); connection.setRequestMethod("GET"); InputStream inputStream=connection.getInputStream(); InputStreamReader isr=new InputStreamReader(inputStream); br=new BufferedReader(isr); String line=null; StringBuilder rezultat=new StringBuilder(); // 用StringBuilder代替字符串拼接,更高效 while((line=br.readLine())!=null) rezultat.append(line); parsareJSON(rezultat.toString()); return rezultat.toString(); } catch (IOException e) { Log.e("AsyncTask", "网络请求异常: " + e.getMessage()); e.printStackTrace(); return null; } finally { // 关闭资源 if (br != null) { try { br.close(); } catch (IOException e) { e.printStackTrace(); } } if (connection != null) { connection.disconnect(); } } }重写onCancelled方法(可选但推荐)
重写该方法可以处理任务崩溃或被取消的情况,避免ProgressDialog一直显示:@Override protected void onCancelled() { super.onCancelled(); if (progressDialog != null && progressDialog.isShowing()) { progressDialog.cancel(); } Log.e("AsyncTask", "任务被取消/崩溃"); }检查JSON数据结构
确认Pastebin返回的JSON结构与解析逻辑匹配,比如键名是否正确(比如numerestaurant是否确实是JSON中的字段名),避免因字段不存在导致解析异常。
内容的提问来源于stack exchange,提问作者Rares Petrescu

