Android中JSON POST请求ProgressBar不显示问题求助
嘿,我帮你定位到问题啦!你的ProgressBar不显示,核心原因是网络请求直接阻塞了UI主线程,导致UI没法及时更新。
问题根源
Android里UI更新(比如设置ProgressBar可见)必须在主线程执行,但耗时的网络请求如果也放在主线程,会把主线程“卡”住——你点击按钮后虽然设置了progressBar.setVisibility(View.VISIBLE),但紧接着就执行了同步的网络请求,主线程被这个请求占满,根本没时间去刷新UI展示ProgressBar。等请求完成后,你又马上把ProgressBar设为GONE,所以它完全没机会显示出来。
解决方案:用异步任务把网络请求移到子线程
我们需要把耗时的网络请求放到子线程,让主线程专心处理UI更新。这里用Android提供的AsyncTask来实现,它能帮我们轻松管理后台任务和UI线程的交互。
修改后的完整代码示例:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_leave); progressBar = findViewById(R.id.progressBarLeave); submit_button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 点击后立刻显示ProgressBar progressBar.setVisibility(View.VISIBLE); // 启动异步任务执行网络请求 new SubmitDataTask().execute(); } }); } // 自定义AsyncTask,负责后台请求和主线程结果处理 private class SubmitDataTask extends AsyncTask<Void, Void, JSONObject> { @Override protected JSONObject doInBackground(Void... voids) { // 这个方法在子线程运行,专门处理耗时操作 try { String api_url = "https://url/"; String json_request = "{\"test\":"+1+"}"; Log.e("driver_loc", json_request); // 修正了你原来写错的变量名 return call_api(api_url, json_request); } catch (Exception e) { e.printStackTrace(); return null; } } @Override protected void onPostExecute(JSONObject response_data) { // 这个方法在主线程运行,处理请求结果和UI更新 progressBar.setVisibility(View.GONE); if (response_data != null) { try { Log.e("response", String.valueOf(response_data)); if(response_data.getString("status").equals("1")) { Toast.makeText(Leave.this, "Success", Toast.LENGTH_LONG).show(); } else { Toast.makeText(Leave.this, "Request failed", Toast.LENGTH_LONG).show(); } } catch (JSONException e) { e.printStackTrace(); Toast.makeText(Leave.this, "Failed to parse response", Toast.LENGTH_LONG).show(); } } else { Toast.makeText(Leave.this, "Network request failed", Toast.LENGTH_LONG).show(); } } } // 保留网络请求方法,但优化异常处理和响应校验 public JSONObject call_api(String api_url, String request_data) { try { URL url = new URL(api_url); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setDoInput(true); conn.setDoOutput(true); // 添加请求头,告诉服务器我们发送的是JSON格式 conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); OutputStream os = conn.getOutputStream(); BufferedWriter writer = new BufferedWriter( new OutputStreamWriter(os, "UTF-8")); writer.write(request_data); writer.flush(); writer.close(); os.close(); // 检查响应码,确保请求成功 int responseCode = conn.getResponseCode(); if (responseCode != HttpURLConnection.HTTP_OK) { Log.e("API Error", "Response Code: " + responseCode); return null; } BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(conn.getInputStream())); StringBuilder response = new StringBuilder(); String line; while ((line = bufferedReader.readLine()) != null) { response.append(line); } bufferedReader.close(); Log.d("API Response", response.toString()); return new JSONObject(response.toString()); } catch (Exception e) { Log.e("API Exception", e.toString()); // 子线程不能弹Toast,只打日志,后续在主线程处理异常提示 return null; } }
几个重要提醒
- 绝对不要在主线程跑网络请求:Android早就禁止这种操作了,轻则UI卡顿,重则触发ANR(应用无响应)崩溃。
- UI操作必须在主线程:像设置ProgressBar、弹Toast这些操作,一定要放在主线程执行,AsyncTask的
onPostExecute就是专门干这个的。 - 异常处理要规范:原来的
call_api里不要弹Toast,因为子线程不能直接操作UI,把异常信息带回主线程再处理。 - 变量名修正:你原来代码里
Log.e("driver_loc", location_request);的location_request是笔误,应该是json_request,我已经帮你修正了。
内容的提问来源于stack exchange,提问作者Geek Boy
相关产品推荐
相关产品推荐

