Xamarin Android应用获取网站JSON数据存入SQLite无响应问题
我来帮你排查下这个问题——调用GetAllPharmacies没反应大概率是几个常见环节出了问题,咱们一步步来梳理并修正:
核心问题排查与修正步骤
1. 异步操作未正确处理(最常见原因)
你当前的方法是void类型,但HttpClient的请求方法都是异步的,如果直接调用而不加await,方法会直接执行完毕,根本没等到网络请求返回就结束了。
修正方法:把方法改成异步任务类型,并在异步操作前加await:
// 修改方法签名为async Task public async Task GetAllPharmacies() { try { var client = new HttpClient(); var uri = "http://no-nonsens..."; // 异步发起请求并等待响应 var response = await client.GetAsync(uri); // 确保请求成功(非2xx状态会抛出异常) response.EnsureSuccessStatusCode(); // 读取返回的JSON字符串 var jsonContent = await response.Content.ReadAsStringAsync(); // ...后续反序列化和DB操作 } catch (Exception ex) { // 关键:捕获异常并打印,才能知道哪里出错 Android.Util.Log.Error("PharmacySync", $"同步失败:{ex.ToString()}"); } }
2. JSON反序列化需匹配实体结构
用Newtonsoft.Json反序列化时,必须保证你的实体类(比如Pharmacy)和接口返回的JSON数组结构完全匹配。如果字段名不一致,要使用JsonProperty特性映射:
public class Pharmacy { // 假设JSON里的字段是"pharmacy_id",实体类用Id [JsonProperty("pharmacy_id")] public int Id { get; set; } [JsonProperty("pharmacy_name")] public string Name { get; set; } // 其他字段同理,必须和JSON结构对应 } // 反序列化代码 var pharmacyList = JsonConvert.DeserializeObject<List<Pharmacy>>(jsonContent);
3. SQLite操作需注意线程安全与执行逻辑
Android上SQLite不建议在UI线程执行耗时操作,而且要确保DB操作代码没有遗漏关键步骤:
// 把DB操作放到后台线程 await Task.Run(() => { // 数据库路径示例(适配Android本地存储) string dbPath = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Pharmacies.db3" ); using (var dbConnection = new SQLiteConnection(dbPath)) { // 先创建表(如果不存在) dbConnection.CreateTable<Pharmacy>(); // 批量插入数据(如果需要去重,可以先删除旧数据再插入) dbConnection.InsertAll(pharmacyList); } });
4. 网络权限与明文请求配置(Android专属)
- 确保
AndroidManifest.xml已经申请网络权限:<uses-permission android:name="android.permission.INTERNET" /> - Android 9及以上默认禁止明文HTTP请求,需要在
application标签里添加配置:<application android:allowBackup="true" android:usesCleartextTraffic="true"> <!-- 允许明文HTTP --> <!-- 其他配置 --> </application>
5. 正确调用异步方法
在调用GetAllPharmacies时,也要用await等待执行完成,比如在MainActivity的OnCreate里:
protected override async void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); SetContentView(Resource.Layout.activity_main); // 调用同步方法 await GetAllPharmacies(); }
完整修正后代码示例
public async Task GetAllPharmacies() { try { var client = new HttpClient(); var uri = "http://no-nonsens..."; // 异步请求并校验响应 var response = await client.GetAsync(uri); response.EnsureSuccessStatusCode(); // 读取JSON内容 var jsonContent = await response.Content.ReadAsStringAsync(); // 反序列化实体集合 var pharmacyList = JsonConvert.DeserializeObject<List<Pharmacy>>(jsonContent); // 后台执行SQLite插入 await Task.Run(() => { string dbPath = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Pharmacies.db3" ); using (var db = new SQLiteConnection(dbPath)) { db.CreateTable<Pharmacy>(); // 可选:先清空旧数据 // db.DeleteAll<Pharmacy>(); db.InsertAll(pharmacyList); } }); Android.Util.Log.Info("PharmacySync", "数据同步成功"); } catch (Exception ex) { Android.Util.Log.Error("PharmacySync", $"同步失败:{ex.ToString()}"); } } // 对应的实体类示例 public class Pharmacy { [JsonProperty("pharmacy_id")] public int Id { get; set; } [JsonProperty("pharmacy_name")] public string Name { get; set; } [JsonProperty("address")] public string Address { get; set; } }
内容的提问来源于stack exchange,提问作者Blackpikin
相关产品推荐
相关产品推荐

