Android中AsyncTask传递的时间字符串无法转为Date对象求助
你遇到的核心问题是代码执行顺序错误——在onCreate方法里,你提前调用了parseDateeb(compareFajrOne)和parseDateeb(compareFajrTwo)解析日期,但此时FectchDetails2这个异步任务还在后台请求API,compareFajrOne和compareFajrTwo还是初始的空字符串"",解析自然会失败;而硬编码时变量一开始就有有效值,所以能正常转换。
另外你的代码里还有个明显的笔误:AsyncTask的onPostExecute里用了compareStringOne和compareStringTwo,但外面定义的变量是compareFajrOne和compareFajrTwo,这也会导致赋值失败。
下面是具体的修复步骤和优化后的代码:
1. 调整执行顺序,等待API数据返回后再解析日期
把日期解析、当前时间获取的逻辑移到AsyncTask的onPostExecute方法里,确保只有当API返回数据并赋值给变量后,再进行日期转换操作。
2. 修正变量名不一致的问题
把onPostExecute里的compareStringOne/compareStringTwo改成compareFajrOne/compareFajrTwo,保证赋值正确。
3. 优化日期解析方法,添加调试日志
避免直接返回new Date(0),而是添加日志输出解析失败的原因,同时处理空字符串的情况,方便排查问题。
4. 点击事件里增加空值判断
防止用户在API数据加载完成前点击按钮,导致空指针异常。
优化后的完整代码示例
public class Main2Activity extends AppCompatActivity { String getdate, getday, gethijri, gettimezone, getfajr, getsunrise, getduhr, getasr, getsunset, getmaghrib, getisha, getimsak; public static final String TIME_FORMAT = "HH:mm"; // 注意:如果API返回的是24小时制时间,用HH;12小时制用hh,根据实际情况调整 String compareFajrOne = ""; String compareFajrTwo = ""; private Date date; private Date dateComparefajrOne; private Date dateComparefajrTwo; private Date dateCompareishaTwo; private Button fajrofer; private final boolean[] ispressed = {false}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.dailynamazrecord); fajrofer = findViewById(R.id.fajrada); // 启动异步任务获取祈祷时间 new FectchDetails2().execute(); fajrofer.setOnClickListener(view -> { // 先判断日期对象是否已初始化,避免空指针 if (date == null || dateComparefajrOne == null || dateComparefajrTwo == null) { Toast.makeText(Main2Activity.this, "正在加载祈祷时间,请稍后", Toast.LENGTH_SHORT).show(); return; } Toast.makeText(Main2Activity.this, compareFajrOne+"\n"+compareFajrTwo+"\n"+dateComparefajrOne+"\n"+date+"\n"+dateComparefajrTwo, Toast.LENGTH_LONG).show(); if (dateComparefajrOne.before(date) && dateComparefajrTwo.after(date)) { if (ispressed[0]) { fajrofer.setBackgroundResource(R.drawable.namazoffered); } else { fajrofer.setBackgroundResource(R.drawable.ofeer); } ispressed[0] = !ispressed[0]; } else { // 注意:这里的p变量你没有贴全代码,需要确保它已正确初始化 if (p != null) showPopup(Main2Activity.this, p); } }); } public class FectchDetails2 extends AsyncTask<String, String, String> { String data = ""; @Override protected String doInBackground(String... params) { try { URL url = new URL("http://api.aladhan.com/v1/timingsByCity?city=Karachi&country=Pakistan&method=8"); HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); InputStream inputStream = urlConnection.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String line; while ((line = bufferedReader.readLine()) != null) { data += line; } JSONObject json = new JSONObject(data); JSONObject gtimings = json.getJSONObject("timings"); // 修正原代码里的json2变量错误 getfajr = gtimings.getString("Fajr"); getsunrise = gtimings.getString("Sunrise"); getduhr = gtimings.getString("Dhuhr"); getasr = gtimings.getString("Asr"); getsunset = gtimings.getString("Sunset"); getmaghrib = gtimings.getString("Maghrib"); getisha = gtimings.getString("Isha"); getimsak = gtimings.getString("Imsak"); } catch (MalformedURLException | IOException | JSONException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(String s) { super.onPostExecute(s); // 修正变量名,正确赋值 compareFajrOne = getfajr; compareFajrTwo = getsunrise; // 此时变量已有有效值,开始解析日期 Calendar now = Calendar.getInstance(); int hour = now.get(Calendar.HOUR_OF_DAY); // 用HOUR_OF_DAY获取24小时制时间,对应HH格式 int minute = now.get(Calendar.MINUTE); date = parseDateeb(Integer.toString(hour)+":"+ Integer.toString(minute)); dateComparefajrOne = parseDateeb(compareFajrOne); dateComparefajrTwo = parseDateeb(compareFajrTwo); } } private Date parseDateeb(String dateStr) { if (TextUtils.isEmpty(dateStr)) { Log.e("DateParse", "待解析的时间字符串为空"); return null; } // SimpleDateFormat不是线程安全的,建议每次使用时创建新实例 SimpleDateFormat inputParser = new SimpleDateFormat(TIME_FORMAT); try { return inputParser.parse(dateStr); } catch (java.text.ParseException e) { Log.e("DateParse", "解析时间失败: " + dateStr, e); return null; } } }
额外建议
如果你的项目支持Android API 26+,推荐使用Java 8的日期时间API(LocalTime、DateTimeFormatter),它们是线程安全的,用法更清晰:
private LocalTime parseTime(String timeStr) { if (TextUtils.isEmpty(timeStr)) { return null; } DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm"); try { return LocalTime.parse(timeStr, formatter); } catch (DateTimeParseException e) { Log.e("TimeParse", "解析时间失败: " + timeStr, e); return null; } }
判断时间范围时可以用:
LocalTime currentTime = LocalTime.now(); if (dateComparefajrOne.isBefore(currentTime) && dateComparefajrTwo.isAfter(currentTime)) { // 执行对应逻辑 }
内容的提问来源于stack exchange,提问作者Ebad Lodhi

