Xamarin.Forms怎样使用高德地图SDK

Xamarin.Forms怎样使用高德地图SDK?本编文章分为2节,第1节是介绍高德地图SDK与Nuget相关的资料,第2节是介绍客户端代码(Xamarin APP)调用SDK时Xamarin.Android与Xamarin.Forms协调交互的方式。

介绍

本编文章分为2节,第1节是介绍高德地图SDK与Nuget相关的资料,第2节是介绍客户端代码(Xamarin APP)调用SDK时Xamarin.AndroidXamarin.Forms协调交互的方式。

Part 1 高德地图SDK与Nuget相关的资料

高德地图SDK在原生Android方面,提供定制下载与使用gradle从Maven或JCenter集成使用,定制下载的方式浏览这个网址:相关下载-Android 地图SDK | 高德地图API,使用gradle集成的方式浏览这个网址:Android Studio 配置工程-创建工程-开发指南-Android 地图SDK

定制下载的方式是开发者勾选需要集成的功能后,高德的网站自动将选择的功能合成一个jar包或aar包,而gradle集成的方式像Nuget安装库一样,安装开发者自己选择的库。在高德SDK没有支持gradle集成前只能使用前者,而前者的缺点就是当所有包分开完成绑定工作后,在App端编译会遇到api冲突的异常。而gradle方式则没有这种问题。

不过要注意的是导航SDK已经包含了地图SDK、猎鹰SDK已经包含了定位SDK;所以导航SDK与地图SDK不能同时集成在APP中,只能两者选一;猎鹰SDK与定位SDK不能同时集成在APP中只能两者选一。

Install-Package XamarinLibrary.Xamarin.Android.Amap.Api.Location -Version 4.9.0
Install-Package XamarinLibrary.Xamarin.Android.Amap.Api.Search -Version 7.3.0
Install-Package XamarinLibrary.Xamarin.Android.Amap.Api.Track -Version 1.3.0
Install-Package XamarinLibrary.Xamarin.Android.Amap.Api.3DMap -Version 7.4.0
Install-Package XamarinLibrary.Xamarin.Android.Amap.Api.Navi3DMap -Version 7.4.0

Part 2 调用SDK时Xamarin.Android与Xamarin.Forms协调交互的方式

  • 代码项目层级关系
Xamarin.Forms怎样使用高德地图SDK 1
Native与Forms

SampleApp这一层其实是.Net Standard类库,而SampleApp.Android这一层则可以看作是main函数所在的一层,通常会把这一层叫做native层。查看native层的Reference会看到它引用了SampleApp这一层,记住这个层级关系有利于分清楚集成第三方SDK与层级调用的关系。

而熟悉.Net Core开发工作的开发者就比较熟悉.Net Standard的作用–跨平台,所以.Net Standard支持的像一系列异步接口、HttpClient、System.Text.Json等这些常用的功能也能直接或通过Nuget安装的方式使用。

但是要注意的是,也因为.Net Standard的跨平台性质,不要将native层的类放到.Net Standard中,例如Android Native的Android.App.Activity类。因为Xamarin.Android能引用.Net Standard,那其他native层如Xamarin.iOS、UWP、WPF也能引用。

所以很多入门Xamarin的开发者的一个问题是Forms的东西怎么在Android或者iOS显示,Android或者iOS的东西怎么在Forms显示。下文讲到的Renderer与MessagingCenter就是其中的两个解决方案。

  • 集成SDK

示例代码中包含了全功能的演示,所以引用了导航SDK(含地图SDK)、猎鹰SDK(含位置SDK)与搜索SDK

Xamarin.Forms怎样使用高德地图SDK
Xamarin.Forms怎样使用高德地图SDK

Xamarin.Forms怎样使用高德地图SDK

根据高德官方文档配置key配置权限这两节教程,配置native层Properties/AndroidManifest.xml文件即可

  • Renderer

界面控件在Android中可以通过xml或者代码创建:

MapView:

mapView = new MapView(this);

AMapNaviView:

    <com.amap.api.navi.AMapNaviView
        android:id="@+id/navi_view"
                         android:layout_width="match_parent"
                         android:layout_height="match_parent"/>

而Xamarin开发需要将这些原生的控件显示到Forms层中,就可以用到Renderer方案,重点是要在override的OnElementChanged函数中将控件设值。

        protected override void OnElementChanged(ElementChangedEventArgs<XAMapNaviView> e)
        {
            mRelativeLayout = (Context as MainActivity).naviRelativeLayout;
            (Context as MainActivity).navi.StartNavi(NaviType.Emulator);
            SetNativeControl(mRelativeLayout);
        }

以上代码中没有使用基类提供的Inflate函数去获取xml的控件,而是放在MainActivity中使用Inflate获取,是因为SDK中的控件需要进行生命周期管理。一般情况下没有生命周期管理的控件都可以在Renderer中使用Inflate函数获取。

  • MessagingCenter

除了原生控件需要在Forms层显示,还需要数据在Forms层与Native层间互相传递,协调代码工作。

这里以高德SDK中查询天气数据为案例进行讲解。

熟悉WPF或者UWP开发工作的.Net开发者比较熟悉以下Forms层中的Xaml代码

        <StackLayout>
            <Label Text="其他数据搜索功能请参照官方文档自行实现"></Label>
            <Label Text="本示例只作天气查询演示"></Label>
            <Button Text="Weather Query" x:Name="WeatherBtn" Clicked="WeatherBtn_Clicked"></Button>
            <Label Text="北京天气"></Label>
            <Label x:Name="ReportTimeLabel"></Label>
            <Label x:Name="WeatherLabel"></Label>
            <Label x:Name="TemperatureLabel"></Label>
            <Label x:Name="WindDirectionLabel"></Label>
            <Label x:Name="WindPowerLabel"></Label>
            <Label x:Name="HumidityLabel"></Label>
        </StackLayout>

用户点击Button,触发了这个Button的Clicked事件

        public const string QueryWeather = "QueryWeather";
        private void WeatherBtn_Clicked(object sender, EventArgs e)
        {
            MessagingCenter.Send(new object(), QueryWeather);
        }

而事件函数的函数体内只是使用了MessagingCenter的Send函数

Xamarin.Forms怎样使用高德地图SDK 2
Xamarin.Forms怎样使用高德地图SDK

通过查找QueryWeather常量的引用可以看到,消息从SampleApp层Send,在SampleApp.Android层Subscribe

这就是MessagingCenter的用法,MessagingCenter是Pub/Sub设计模式(发布订阅设计模式)的一种实现的类。

订阅了这个消息的native层,在forms层发布消息的时候就会收到触发调用的通知。

继续将业务往下发展

            MessagingCenter.Subscribe<object>(this, SearchPage.QueryWeather, sender =>
            {
                //检索参数为城市和天气类型,实况天气为WEATHER_TYPE_LIVE、天气预报为WEATHER_TYPE_FORECAST
                var mquery = new WeatherSearchQuery("北京", WeatherSearchQuery.WeatherTypeLive);
                var mweathersearch = new WeatherSearch(this);
                mweathersearch.SetOnWeatherSearchListener(new OnWeatherSearchListener());
                mweathersearch.Query=mquery;
                mweathersearch.SearchWeatherAsyn(); //异步搜索 
            });

当订阅者收到通知后触发查询天气的函数(高德SDK查询天气相关的函数)

查询天气的函数执行成功或者失败后,都会触发OnWeatherSearchListener类内的回调函数OnWeatherLiveSearched

如果天气查询成功了可以使用MessagingCenter将天气数据打包后发送回给forms层,为什么是打包后发送而不是将高德sdk的result变量发送呢,因为高德sdk的result变量不是跨平台的,是不存在于.Net Standard中的,是带有java平台相关的类或者成员的。

所以我们可以像服务器开发工作一般的处理方法一样,使用DTO(data transfer object)传递数据,DTO在这里就只是.Net Standard中的一个自定义类

    public class WeatherModel
    {
        public string ReportTime { get; set; }
        public string Weather { get; set; }
        public string Temperature { get; set; }
        public string WindDirection { get; set; }
        public string WindPower { get; set; }
        public string Humidity { get; set; }
    }
                    var weatherlive = weatherLiveResult.LiveResult;
                    var model = new WeatherModel 
                    {
                        ReportTime= weatherlive.ReportTime,
                        Humidity= weatherlive.Humidity,
                        Temperature= weatherlive.Temperature,
                        Weather= weatherlive.Weather,
                        WindDirection= weatherlive.WindDirection,
                        WindPower= weatherlive.WindPower
                    };

                    //发回给forms层
                    MessagingCenter.Send(new object(), SearchPage.QueryWeatherOk, model);

再通过查找QueryWeatherOK常量的引用,这时会看到接收者就是Sample.App层,而发送者就是Sample.Android层

Xamarin.Forms怎样使用高德地图SDK 3
数据回发到Forms层

最后在Forms层将数据设置到Xaml中的Label控件完成整个天气的查询业务

        protected override void OnAppearing()
        {
            MessagingCenter.Subscribe<object, WeatherModel>(this, QueryWeatherOk, (sender, args) => 
            {
                Xamarin.Essentials.MainThread.BeginInvokeOnMainThread(() => 
                {
                    ReportTimeLabel.Text = $"{args.ReportTime}发布";
                    WeatherLabel.Text = args.Weather;
                    TemperatureLabel.Text = $"{args.Temperature}°";
                    WindDirectionLabel.Text = $"吹{args.WindDirection}风";
                    WindPowerLabel.Text = $"风力{args.WindPower}级";
                    HumidityLabel.Text = $"湿度{args.Humidity}";
                });
            });
        }

总结一下整个代码的流程如下图,Forms层发送消息,Native层订阅消息后查询天气,天气查询的回调函数将结果回发到Forms层,Forms层通过UI控件显示数据。

Xamarin.Forms怎样使用高德地图SDK 4
查询天气序列图

App代码参看

https://github.com/jingliancui/XamarinFormsAMapSDKSample

本文转载自知乎,原文链接:https://zhuanlan.zhihu.com/p/139712723

本站最新优惠

Namesilo优惠:新用户省 $1 域名注册-优惠码:45D%UYTcxYuCloZ 国外最便宜域名!点击了解更多

特别优惠:免费赠送 $100 Vultr主机-限时优惠!英文站必备海外服务器!点击了解更多

VPS优惠:搬瓦工优惠码:BWH3OGRI2BMW 最高省5.83%打开外面世界的一款主机点击了解更多

本文来自投稿作者:IT菜鸟,不代表江湖人士立场,如若转载,请注明出处:https://jhrs.com/2020/37393.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注

10 − 1 =