如何在Android Fragment的ListView中通过PHP显示MySQL数据
嘿,我来帮你把ListView的静态数据改成从MySQL+PHP接口获取的动态数据,分后端和前端两部分一步步来:
一、先写后端PHP接口(从MySQL取数据并返回JSON)
首先你需要一个PHP文件来连接数据库、查询数据,然后把结果以JSON格式返回——这是Android端最容易解析的格式。把下面的代码保存为get_data.php,上传到你的服务器(比如阿里云ECS、虚拟主机都行):
<?php // 替换成你的数据库配置 $servername = "localhost"; // 一般是localhost,远程的话填服务器IP $username = "your_db_username"; $password = "your_db_password"; $dbname = "your_db_name"; // 创建数据库连接 $conn = new mysqli($servername, $username, $password, $dbname); // 检查连接是否成功 if ($conn->connect_error) { die("数据库连接失败: " . $conn->connect_error); } // 替换成你的查询语句,这里假设你有一个叫`service_items`的表,字段是id、name、desc $sql = "SELECT id, name, `desc` FROM service_items"; $result = $conn->query($sql); $response = array(); if ($result->num_rows > 0) { // 遍历查询结果,存入数组 while($row = $result->fetch_assoc()) { $response[] = $row; } } // 设置返回头为JSON格式,然后输出数据 header('Content-Type: application/json; charset=utf-8'); echo json_encode($response, JSON_UNESCAPED_UNICODE); // 关闭连接 $conn->close(); ?>
上传后,用浏览器访问这个PHP文件的地址(比如http://你的域名/get_data.php),如果能看到类似[{"id":"1","name":"服务1","desc":"这是第一个服务"},...]的JSON数据,说明后端接口没问题了。
二、修改Android Fragment代码,实现网络请求和数据展示
接下来调整你的ServiceFragment,主要做这几件事:添加网络权限、发起网络请求、解析JSON、更新ListView。
1. 添加必要权限和配置
在AndroidManifest.xml里添加网络权限:
<uses-permission android:name="android.permission.INTERNET" />
如果你的Android版本是9及以上,默认禁止明文HTTP请求,要么把PHP接口改成HTTPS,要么在res/xml目录下新建network_security_config.xml:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config cleartextTrafficPermitted="true" /> </network-security-config>
然后在AndroidManifest.xml的application标签里引用这个配置:
<application ... android:networkSecurityConfig="@xml/network_security_config"> ... </application>
2. 准备数据模型类
创建一个ServiceItem.java类,用来对应数据库里的字段:
public class ServiceItem { private String id; private String name; private String desc; public ServiceItem(String id, String name, String desc) { this.id = id; this.name = name; this.desc = desc; } // Getter方法,供Adapter调用 public String getId() { return id; } public String getName() { return name; } public String getDesc() { return desc; } }
3. 修改ServiceFragment代码
这里用OkHttp来做网络请求(比原生的HttpURLConnection更简洁,AsyncTask已经被废弃了),先在build.gradle(Module)的dependencies里添加OkHttp依赖:
implementation 'com.squareup.okhttp3:okhttp:4.10.0'
然后更新你的Fragment代码:
public class ServiceFragment extends Fragment { private ListView listView; private List<ServiceItem> serviceItemList = new ArrayList<>(); private ArrayAdapter<ServiceItem> adapter; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // 加载布局 View view = inflater.inflate(R.layout.fragment_service, container, false); // 绑定ListView listView = view.findViewById(R.id.your_listview_id); // 替换成你布局里的ListView ID // 初始化适配器,这里用自定义的列表项显示逻辑 adapter = new ArrayAdapter<ServiceItem>(getContext(), android.R.layout.simple_list_item_2, serviceItemList) { @Override public View getView(int position, View convertView, ViewGroup parent) { View itemView = super.getView(position, convertView, parent); // 获取布局里的两个TextView,分别显示名称和描述 TextView tvName = itemView.findViewById(android.R.id.text1); TextView tvDesc = itemView.findViewById(android.R.id.text2); ServiceItem item = serviceItemList.get(position); tvName.setText(item.getName()); tvDesc.setText(item.getDesc()); return itemView; } }; listView.setAdapter(adapter); // 发起网络请求获取数据 loadDataFromServer(); return view; } private void loadDataFromServer() { // 替换成你的PHP接口地址 String url = "http://你的域名/get_data.php"; OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder().url(url).build(); // 异步发起请求,避免阻塞主线程 client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { // 请求失败,在主线程弹出提示 requireActivity().runOnUiThread(() -> { Toast.makeText(getContext(), "网络请求失败,请检查网络", Toast.LENGTH_SHORT).show(); }); } @Override public void onResponse(Call call, Response response) throws IOException { if (response.isSuccessful() && response.body() != null) { String jsonStr = response.body().string(); try { // 解析JSON数组 JSONArray jsonArray = new JSONArray(jsonStr); for (int i = 0; i < jsonArray.length(); i++) { JSONObject jsonObj = jsonArray.getJSONObject(i); String id = jsonObj.getString("id"); String name = jsonObj.getString("name"); String desc = jsonObj.getString("desc"); serviceItemList.add(new ServiceItem(id, name, desc)); } // 在主线程更新ListView requireActivity().runOnUiThread(() -> { adapter.notifyDataSetChanged(); }); } catch (JSONException e) { e.printStackTrace(); requireActivity().runOnUiThread(() -> { Toast.makeText(getContext(), "数据解析错误", Toast.LENGTH_SHORT).show(); }); } } } }); } }
三、注意事项
- 所有占位符(比如数据库信息、接口地址、ListView ID、表字段)都要替换成你自己的实际内容。
- 网络请求必须在子线程执行,这里用OkHttp的异步回调已经处理了,不要直接在主线程做网络操作。
- 如果需要更复杂的列表项布局,可以自定义
BaseAdapter或者用RecyclerView替代ListView(推荐后者,功能更强大)。 - 可以添加加载状态提示(比如ProgressBar),提升用户体验。
内容的提问来源于stack exchange,提问作者kane kayp

