Android Java开发:如何等待异步函数getCards()执行完成?
Hey there, let's tackle this common asynchronous loading problem you're running into. The core issue here is that your getCards() method uses an asynchronous network request (Volley's StringRequest), which doesn't block the main thread. When you call getCards() and immediately try to read from SharedPreferences, the network request hasn't finished yet—so there's no data to read. Your quick fix with wait(100) crashed because wait() requires a synchronized block, and even if it worked, blocking the main thread would cause an ANR (Application Not Responding) error.
Here's how to properly fix this:
1. Move UI Updates to the Network Request Callback
Since the network request finishes in the onResponse() method, that's the perfect place to update your TextViews—right after you've saved the data to SharedPreferences. This ensures you only update the UI when the data is actually ready.
First, add a helper method to handle UI updates cleanly:
private void updateCardDisplay(String cardNumber, String fullName) { if (fullName == null || cardNumber == null) { tvccnumber.setText("No card was added!"); tvccfullname.setText("No card was added!"); } else { tvccnumber.setText(cardNumber); tvccfullname.setText(fullName); } }
Then modify your getCards() method to call this helper once the data is saved:
public void getCards(){ StringRequest stringRequest = new StringRequest(Request.Method.POST, Constants.GETC_URL, new Response.Listener<String>() { @Override public void onResponse(String response) { if(!response.contains("Error!")){ try { JSONArray jsonArray = new JSONArray(response); JSONObject jsonObject = jsonArray.getJSONObject(0); String ccnumber = jsonObject.getString("ccNumber"); String ccsignature = jsonObject.getString("ccSign"); String fullname = jsonObject.getString("fullName"); // Save to SharedPreferences editor.putString("ccnumber", ccnumber); editor.putString("ccsignature", ccsignature); editor.putString("fullname", fullname); editor.commit(); // Update UI now that data is ready updateCardDisplay(ccnumber, fullname); } catch (JSONException e) { e.printStackTrace(); updateCardDisplay(null, null); Toast.makeText(FinalUserSpace.this, "Failed to parse card data", Toast.LENGTH_SHORT).show(); } }else{ Toast.makeText(FinalUserSpace.this, response, Toast.LENGTH_SHORT).show(); updateCardDisplay(null, null); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { error.printStackTrace(); updateCardDisplay(null, null); Toast.makeText(FinalUserSpace.this, "Network error: Couldn't load card data", Toast.LENGTH_SHORT).show(); } }); // Don't forget to add the request to your Volley RequestQueue! requestQueue.add(stringRequest); }
2. Initialize with Loading State
In your main activity code, set a loading state before calling getCards() so users know something's happening:
// Set loading state first tvccnumber.setText("Loading card data..."); tvccfullname.setText("Loading card data..."); // Trigger the network request getCards();
3. Refresh UI When Returning to the Activity
To keep the UI updated when switching back from another Activity, add this to your onResume() method:
@Override protected void onResume() { super.onResume(); // Read from SharedPreferences and update UI String ccnr = pref.getString("ccnumber", null); String ccfn = pref.getString("fullname", null); updateCardDisplay(ccnr, ccfn); }
Why Your Previous wait() Approach Failed
wait()must be called inside asynchronizedblock, which you didn't do—this caused the crash.- Even if you fixed that, blocking the main thread with
wait()would freeze your app and trigger an ANR, since the main thread can't handle user input or UI updates while blocked.
This approach ensures your UI only updates when data is available, avoids blocking the main thread, and keeps the experience smooth for users.
内容的提问来源于stack exchange,提问作者mrMan

