Xamarin调用API更新Google Map图钉信息不生效问题咨询
问题描述
需要将直连数据库的逻辑替换为调用API(接口地址:http://194.141.118.43:3001/stations)。
我使用以下代码直连MySQL数据库修改图钉信息,可以成功更新:
public async void DatabaseConnection(List<CustomPin> pins) { string ConnectionString = "server=192.168.0.1;uid=user;port=4444;pwd=pass;database=dbName;"; MySqlConnection Conn = new MySqlConnection(ConnectionString); try { Conn.Open(); string query = "SELECT * FROM sel_alert_level s;"; MySqlCommand myCommand = new MySqlCommand(query, Conn); MySqlDataReader myReader; myReader = myCommand.ExecuteReader(); try { while (myReader.Read()) { int codeNum = myReader.GetInt32(4); int level = myReader.GetInt32(3); int mapCode = myReader.GetInt32(0); foreach (var item in pins) { if (item.CodeNum == codeNum) { item.AlertLevel = level; item.CodeNum = codeNum; item.MapCode = mapCode; //await DisplayAlert("Alert", mapCode.ToString(), "ok"); } } //await DisplayAlert("Database Connection", "Connected .." + Environment.NewLine + myReader.GetInt32(0) + Environment.NewLine + myReader.GetString(1) + Environment.NewLine + myReader.GetString(2) + Environment.NewLine + myReader.GetInt32(3) + Environment.NewLine + myReader.GetInt32(4), "OK"); } } finally { myReader.Close(); Conn.Close(); } } catch (Exception ex) { await DisplayAlert("Database Connection", "Not Connected ..." + Environment.NewLine + ex.ToString(), "OK"); } }
运行效果截图:
现在我基于API响应实现了相同逻辑的APIConnection方法,想要实现和DatabaseConnection一样的更新效果,但是无法生效:
public async void APIConnection(List<CustomPin> pins) { try { WaterBindingData waterData = await _restServiceData.GetWaterDataForecast(GenerateRequestUriStations(Constants.EndPoint), GenerateRequestUri(Constants.EndPoint)); foreach (var water in waterData.WaterStation.Stations) { foreach (var item in pins) { if (item.CodeNum == water.CodeNum) { item.AlertLevel = water.AlertLevelStation; item.CodeNum = water.CodeNum; item.MapCode = water.MapCode; } } } } catch (Exception ex) { await DisplayAlert("Data Alert", "Error:" + Environment.NewLine + ex.ToString(), "OK"); } }
该方法运行无报错,waterData能正常拿到返回数据,循环中的if判断也能正常命中,但CustomPin的MapCode等属性不会被修改,最终图钉信息无变化,效果截图如下:


我在构造函数中按如下方式调用两个方法:
DatabaseConnection(customMap.CustomPins); APIConnection(customMap.CustomPins);
项目启动时收到如下警告:
/Applications/Visual Studio.app/Contents/Resources/lib/monodevelop/bin/MSBuild/Current/bin/Microsoft.Common.CurrentVersion.targets(5,5): Warning MSB3276: Found conflicts between different versions of the same dependent assembly. Please set the "AutoGenerateBindingRedirects" property to true in the project file. (MSB3276) (MaritsaTundzhaForecast.iOS)
我查阅了相关官方文档,但我使用Mac版Visual Studio,项目只有"options"选项没有"properties"入口,无法按文档配置。
请问是否是该警告导致图钉信息无法更新?还有哪些可能的原因导致该问题?
问题解答
关于MSB3276警告
这个警告和你当前遇到的图钉属性无法更新的问题没有直接关联,它只是程序集版本冲突的提示,不会影响运行时的属性赋值逻辑。要解决这个警告你可以直接手动编辑你的iOS项目的.csproj文件,在第一个<PropertyGroup>节点下添加<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>即可,不需要通过IDE的配置入口。
图钉属性不更新的核心原因
你的问题出在异步方法的调用逻辑上:
- 你定义的
APIConnection是async void类型的异步方法,这类方法在调用后无法等待执行完成,你在构造函数里同步调用APIConnection的时候,方法执行到await _restServiceData.GetWaterDataForecast就会立即返回,剩下的逻辑会在网络请求完成后才执行。而此时构造函数已经执行完成,界面已经完成了初始渲染,自然看不到更新效果。 - 对比可以正常运行的
DatabaseConnection方法,它虽然也标注了async,但整个方法内部没有用到await关键字,所以实际上是同步执行完了所有的数据库读取、属性赋值逻辑,构造函数执行完的时候属性已经更新完成,所以可以正常显示。
修复方案
- 把
APIConnection方法的返回值从async void改成async Task,DatabaseConnection如果没有异步逻辑也可以直接去掉async关键字。 - 不要在构造函数里调用异步方法,把调用逻辑移到页面的
OnAppearing这类生命周期方法里,用await关键字等待APIConnection执行完成。 - 如果你的
CustomPin类实现了INotifyPropertyChanged接口,属性赋值后会自动通知界面更新;如果没有实现,你可以在赋值完成后手动触发地图的刷新逻辑,比如重新给CustomPins赋值或者调用地图的刷新方法。
内容的提问来源于stack exchange,提问作者Blagovest Pizhev
相关产品推荐
相关产品推荐

