
本文详解因 json 解析类型不匹配(误将 jsonobject 当作 jsonarray 解析)导致的变量初始化失败问题,并提供完整的 php 后端与 android 前端修复方案,确保用户数据在 activity 生命周期中持久、准确地加载。
本文详解因 json 解析类型不匹配(误将 jsonobject 当作 jsonarray 解析)导致的变量初始化失败问题,并提供完整的 php 后端与 android 前端修复方案,确保用户数据在 activity 生命周期中持久、准确地加载。
在 Android 开发中,Activity 重启时成员变量“被重置为 0”,表面看是状态丢失,实则往往源于异步数据加载失败且错误被静默吞没。你遇到的问题正属于典型场景:getData() 方法通过 Volley 请求 PHP 接口获取玩家数据,但变量始终为默认值(如 gold = 0),根本原因并非 Activity 重建本身,而是 JSON 解析逻辑崩溃后未暴露异常,导致赋值语句从未执行。
? 核心问题定位:JSON 类型不匹配
你的 PHP 脚本返回的是标准 JSON 对象({ "gold": 600, "level": 3, ... }),但 Android 端却尝试用 JSONArray 解析:
// ❌ 错误:服务端返回的是 JSONObject,不是 JSONArray
JSONArray array = new JSONArray(response); // ← 这里会抛出 JSONException!
for(int i = 0; i < array.length(); i++){
JSONObject object = array.getJSONObject(i); // ← 永远不会执行到
gold = object.getInt("gold"); // ← 赋值永远不会发生
}由于 catch (Exception e) { } 是空实现,该异常被完全忽略,gold 等变量维持 Java 默认初始值 0,造成“每次重启都归零”的假象。
远程控制 Android 设备,支持截图、自动化操作手机 App 等功能。本应用使用 uiautomator2 作为底层框架,通过 ADB 连接设备,用户无需 Root(1)查看手机屏幕;(2)自动化操作手机 App;(3)远程安装/卸载应用……
✅ 正确做法:精准解析 + 可靠日志
1. 修正 Android 端 JSON 解析(推荐方式)
将 JSONArray 替换为 JSONObject,并添加有效错误日志:
private void getData() {
StringRequest stringRequest = new StringRequest(
Request.Method.GET,
URL,
response -> {
try {
// ✅ 正确:直接解析为 JSONObject(服务端返回单个对象)
JSONObject jsonObject = new JSONObject(response);
gold = jsonObject.getInt("gold");
goldMultiplier = jsonObject.getInt("goldMulti");
xp = jsonObject.getInt("xp");
xpMultiplier = jsonObject.getInt("xpMulti");
xpMax = jsonObject.getInt("xpMax");
xpMaxMulti = jsonObject.getInt("xpMaxMulti");
dmg = jsonObject.getInt("dmg");
dmgMultiplier = jsonObject.getInt("dmgMulti");
bossCount = jsonObject.getInt("bossCount");
bossHP = jsonObject.getInt("bossHp");
bossHPMultiplier = jsonObject.getInt("bossHpMulti");
level = jsonObject.getInt("level");
backgroundCount = jsonObject.getInt("backgroundCount");
// ✅ 关键:UI 更新必须在主线程(onResponse 已保证)
updateUi(); // 将 TextView 更新提取为独立方法,避免重复代码
} catch (JSONException e) {
// ✅ 强制记录错误,不再静默失败
Log.e("MainActivity", "Failed to parse JSON response", e);
Toast.makeText(this, "数据加载失败: " + e.getMessage(),
Toast.LENGTH_LONG).show();
}
},
error -> {
Log.e("MainActivity", "Network request failed", error);
Toast.makeText(this, "网络请求失败: " + error.toString(),
Toast.LENGTH_SHORT).show();
}
);
Volley.newRequestQueue(this).add(stringRequest);
}
// 提取 UI 更新逻辑,避免在 onCreate/onStart 中重复书写
private void updateUi() {
if (levelText != null) levelText.setText("Level: " + level);
if (goldText != null) goldText.setText("Gold: " + gold);
if (bossHealthText != null) bossHealthText.setText("HP: " + bossHP);
if (bossNumberText != null) bossNumberText.setText("Boss: " + bossCount);
}2. 优化 PHP 端(增强健壮性与安全性)
当前 PHP 存在严重 SQL 注入风险(直接拼接 $username)且未处理查询失败。请立即更新为参数化查询,并确保返回格式一致:
<?php
require "conn.php";
// ✅ 使用 POST 参数(更安全)或从 token 获取用户名,禁止硬编码
$username = $_POST['LoggedInUser'] ?? 'test'; // 或从 session/token 验证
// ✅ 使用参数化查询防止 SQL 注入
$stmt = $conn->prepare("SELECT gold, goldMulti, xp, xpMulti, xpMax, xpMaxMulti, dmg, dmgMulti, bossCount, bossHp, bossHpMulti, level, backgroundCount FROM users WHERE username = ?");
$stmt->bind_param("s", $username);
$stmt->execute();
$result = $stmt->get_result();
if ($result && $result->num_rows > 0) {
$row = $result->fetch_assoc();
// ✅ 直接输出 JSON 对象(非数组),与 Android 端保持一致
header('Content-Type: application/json');
echo json_encode($row);
} else {
// ✅ 返回明确错误,便于前端调试
http_response_code(404);
echo json_encode(['error' => 'User not found']);
}
?>3. 补充关键注意事项
- 生命周期调用时机:onCreate() 中调用 getData() 是合理的,但 onStart() 再次调用会导致重复请求。建议仅在 onCreate() 中加载一次,或使用 ViewModel + LiveData 实现数据持久化。
- 空指针防护:updateUi() 中对 TextView 添加 null 检查,避免 findViewById() 返回 null 时崩溃。
-
网络权限:确认 AndroidManifest.xml 中已声明:
<uses-permission android:name="android.permission.INTERNET" />
- HTTPS 迁移:生产环境务必使用 HTTPS,避免明文传输敏感数据;Android 9+ 默认禁用 HTTP,需配置 android:usesCleartextTraffic="true"(临时方案,不推荐长期使用)。
通过以上修正,你的应用将能稳定加载服务器数据,变量不再“神秘归零”。记住:永远不要留空 catch 块——它是调试的第一道防线;而精准匹配 JSON 结构,则是网络通信可靠性的基石。

















