Android使用JDBC从MySQL取数据填充ListView失败,无日志输出求助
我来帮你捋捋这个问题哈,你遇到的情况很典型——AsyncTask没干活、日志还没输出,大概率是这几个地方出了问题:
1. 先确认AsyncTask是否真的启动了
很多新手会写完AsyncTask类,但忘了在主线程调用execute()方法触发执行。比如你得在Activity的onCreate()或者合适的生命周期方法里加:
new YourAsyncTask().execute();
要是没这一步,整个异步任务根本不会跑,自然啥日志都看不到。
2. 检查Try-Catch是否吞了异常
从你贴的代码片段看,doInBackground()里的try块没写完,大概率是没加catch分支,或者catch里没打日志。比如如果你的代码是这样:
@Override protected String doInBackground(Void... params) { try { Connection con = connectionClass.CONN(); if (con == null) { z = "Please check your internet connection"; } else { String query = "select name from medicines"; Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(query); // 处理ResultSet的逻辑... } } catch (Exception e) { // 这里啥都没写?那异常直接被吞了! } return z; }
不管是连接数据库出错,还是SQL执行报错,异常都不会输出到Logcat。你得在catch里强制打日志,把异常栈也带上:
catch (Exception e) { Log.e("DB_ERROR", "数据库操作失败", e); // 一定要打印异常栈,方便定位问题 z = "错误信息:" + e.getMessage(); }
3. 排查ConnectionClass的CONN()方法
你的connectionClass.CONN()可能本身就抛出了异常,但方法内部没处理,直接让异常冒泡到doInBackground,或者CONN()内部吞了异常只返回null,却没打日志。
建议给CONN()方法也加上日志输出:
public Connection CONN() { try { // 你的数据库连接初始化代码... Log.d("CONN_DEBUG", "尝试建立数据库连接"); return connection; } catch (Exception e) { Log.e("CONN_ERROR", "连接数据库失败", e); return null; } }
这样能确认连接过程中有没有出问题。
4. 别忘了加网络权限
AndroidManifest.xml里必须加网络权限,否则连不上远程MySQL:
<uses-permission android:name="android.permission.INTERNET" />
要是没加,CONN()肯定返回null,但你只给z赋值了字符串,却没把z输出到日志,所以也不知道是这个原因。建议在判断con==null时打日志:
if (con == null) { z = "Please check your internet connection"; Log.e("CONN_NULL", z); // 加这行日志,快速定位网络问题 }
5. 补全AsyncTask的onPostExecute方法
要把数据填充到ListView,必须在onPostExecute()里操作(因为不能在doInBackground里更新UI)。比如:
@Override protected void onPostExecute(String result) { super.onPostExecute(result); // 把从ResultSet里拿到的列表数据设置给ListView的Adapter ArrayAdapter<String> adapter = new ArrayAdapter<>(YourActivity.this, android.R.layout.simple_list_item_1, medicineNames); listView.setAdapter(adapter); // 同时打印任务结果日志 Log.d("TASK_RESULT", result); }
注意:你需要在AsyncTask类里定义一个成员变量(比如List<String> medicineNames),在doInBackground遍历ResultSet时把数据存进去。
最后给你一个完整的AsyncTask示例框架,你可以参考着调整:
public class FetchMedicinesTask extends AsyncTask<Void, Void, String> { private List<String> medicineNames = new ArrayList<>(); private ListView listView; private Context context; public FetchMedicinesTask(Context context, ListView listView) { this.context = context; this.listView = listView; } @Override protected void onPreExecute() { super.onPreExecute(); Log.d("TASK_DEBUG", "开始执行异步任务"); // 这里可以显示加载进度条 } @Override protected String doInBackground(Void... params) { String z = ""; try { Connection con = connectionClass.CONN(); if (con == null) { z = "请检查网络连接"; Log.e("CONN_ERROR", z); } else { String query = "select name from medicines"; Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(query); while (rs.next()) { String medicineName = rs.getString("name"); medicineNames.add(medicineName); Log.d("DB_DATA", "获取到药品:" + medicineName); } z = "成功加载" + medicineNames.size() + "条数据"; con.close(); } } catch (Exception e) { z = "数据库操作失败:" + e.getMessage(); Log.e("DB_ERROR", z, e); } return z; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); // 更新ListView ArrayAdapter<String> adapter = new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, medicineNames); listView.setAdapter(adapter); Log.d("TASK_FINISH", result); } }
然后在Activity里启动任务:
ListView listView = findViewById(R.id.your_listview_id); new FetchMedicinesTask(this, listView).execute();
按这个步骤排查,应该能找到问题所在,Logcat也会有对应的日志输出了。
内容的提问来源于stack exchange,提问作者Mr. Benbenbenbenben

