从Xamarin.Essentials谈Xamarin库的封装

2023-11-06 15:58
文章标签 封装 xamarin essentials

本文主要是介绍从Xamarin.Essentials谈Xamarin库的封装,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

编者语:Xamarin在国内的推广还需要努力,其实这真的是移动端开发的一大福音,毕竟用一份代码的时间可以生成iOS/Android/Windows/Linux/macOS/Tizen多个平台,而且是原生的性能。Xamarin在Build 2018发布的新功能有Xamarin.Essentials(点击查看) , Hyper-V for Xamarin Android Emulator ,还有Xamarin.Forms 3.0。Xamarin.Forms 3.0 和 Xamarin.Essentials 都会是一个质的飞跃。Xamarin.Forms 有全新的布局FlexLayout ,更好地和原生控件对接,还新增支持GTK+/Tizen。而Xamarin.Essentials的发布则大大提升开发的效率,把因为平台差异造成的代码不一致的底层接口重新做了归一,这样做提升了编码效率。

    在Build2018前的两周左右,我拿到了Xamarin.Essentials的测试版本(基于nda我只能等到现在才能发布),这是一个为访问一些设备硬件和底层给iOS/Android/UWP三个平台做的统一接口,适配了.NET Standard 2.0(当然也包含.NET Standard 1.0 / iOS / Android)。通过Xamarin.Essentails你可以非常快捷地访问不同平台的摄像头,地理位置,网络检测,更能调用如打电话,相册,通讯录等相当方便实用。如我需要了解设备信息的时候,通过Xamarin.Essentails就是一句非常简单的话就可以完成了
 

640?wx_fmt=png&wxfrom=5&wx_lazy=1 


      运行生成效果
      

640?wx_fmt=png


     话说回来,在Xamarin.Essential之前,其实Xamarin也推出了Xamarin.Mobile(点击查看)和Plugin(点击查看) 。我们先来看看这两位旧人所做的事,如果对比代码其实也差不多,通过PCL的方式对设备底层API进行访问。(ps : 图一是Xamarin.Mobile , 图二Xamarin.Plugins)
      640?wx_fmt=png   640?wx_fmt=png
      看看上面的代码是比较有趣,可以预想到用原生方法写一个摄像头调用你可能需要更多的工作,而且这更接近.NET程序员的使用习惯。假若你希望为Xamarin打造一个跨平台的,也能针对不同平台底层操作,又有一个通用接口的库,这三个通用组件的源码就是很好的教程。
      在Xamarin中实现跨平台访问,方法有几种:
      1. 通过检测平台的方式,最常用的是宏定义        

<span style="font-size:12px;">
#if __IOS__

// iOS-specific code

#endif

#if __TVOS__

// tv-specific stuff

#endif

#if __WATCHOS__

// watch-specific stuff

#endif

#if __ANDROID__

// Android-specific code

#endif

</span>
  2. 或者通过代码的方式, Xamarin.Forms.Device.Idiom去完成

<span style="font-size:12px;">          
          if (Xamarin.Forms.Device.Idiom == TargetIdiom.Phone)

            {

                MainPage = new NavigationPage(new MyPage());

            }

            else if(Xamarin.Forms.Device.Idiom == TargetIdiom.Tablet)

            {

        // etc

            }

            else if(Xamarin.Forms.Device.Idiom == TargetIdiom.Desktop)

            {

        // etc

            }

            else if (Xamarin.Forms.Device.Idiom == TargetIdiom.Unsupported)

            {

                // etc

            }

            else

            {

                // etc

            }</span>

 这个方式除了在代码也可以在XAML

<span style="font-size:12px;">   
<OnIdiom x:TypeArguments="View">

      <OnIdiom.Phone>

      <Grid>

          <Label Text="Phone content view" />

        </Grid>

      </OnIdiom.Phone>

      <OnIdiom.Tablet>

        <Grid>

          <Label Text="Tablet content view" />

        </Grid>

      </OnIdiom.Tablet>

    </OnIdiom></span>

  3. 用DependencyService,在通过公用层生成接口,再在不同平台上实现。这是在Xamarin中最常用的方法,
        640?wx_fmt=png
      回到封装库,首先要定下一个目标就是做个.NET Standard的库,而不再是做PCL. 还有做这种通用库更应该考虑兼容多平台,如iOS/Android/UWP等。以往的做法你可能需要搭建很多的目录,然后去继承一个公共接口去完成。现在通过MSBuild.Sdk.Extras(点击查看), 通过MSBuild可以对不同平台进行快速编译,生成跨平台的库。参考Xamarin.Essentials(点击进入),我自己开始编写一个简单的库。先看看实现原理(如图)
       

640?wx_fmt=png


       在.NET Standard 项目中你可以针对不同平台进行编译,利用第三方的MSBuild.Sdk.Extras进行不同平台库的生成工作,在这种方法上你不再需要上面提到的宏定义或Dependency Service,只需要针对预先设置好的文件进行跨平台编译,这大大方便了代码的管理和维护。xx.standard.cs是一个公用的文件,相当于为不同平台定义了一个接口,而具体实现放到各自平台上如xx.ios.cs , xx.android.cs ..... 最后通过shared封装公共方法暴露给不同项目访问。

<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">

  <PropertyGroup>

    <!--Work around so the conditions work below-->

    <TargetFrameworks>netstandard1.0;netstandard2.0;Xamarin.iOS10;MonoAndroid71;</TargetFrameworks>

    <Product>$(AssemblyName)($(TargetFramework))</Product>

    <EnableDefaultCompileItems>false</EnableDefaultCompileItems>

    <EnableDefaultItems>false</EnableDefaultItems>

    <BuildOutputTargetFolder>$(TargetFramework)</BuildOutputTargetFolder>

  </PropertyGroup>

   <PropertyGroup Condition=" '$(Configuration)'=='Debug' ">

    <DebugType>full</DebugType>

    <DebugSymbols>true</DebugSymbols>

  </PropertyGroup>

  <PropertyGroup Condition=" '$(Configuration)'=='Release' ">

    <DebugType>pdbonly</DebugType>

  </PropertyGroup>  


  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">

    <OutputPath>bin\Debug\$(TargetFramework)</OutputPath>

  </PropertyGroup>

  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">

    <OutputPath>bin\Release\$(TargetFramework)</OutputPath>

  </PropertyGroup>


  <ItemGroup>

    <PackageReference Include="MSBuild.Sdk.Extras" Version="1.4.0" PrivateAssets="All" />

    <Compile Include="**\*.shared.cs" />

  </ItemGroup>

  <ItemGroup Condition=" $(TargetFramework.StartsWith('netstandard'))">

    <Reference Include="System.Numerics" />

    <Reference Include="System.Numerics.Vectors" />

    <Compile Include="**\*.netstandard.cs" />

  </ItemGroup>

  <ItemGroup Condition=" $(TargetFramework.StartsWith('MonoAndroid'))">

    <PackageReference Include="Xamarin.Android.Support.CustomTabs" Version="25.4.0.2" />

    <PackageReference Include="Xamarin.Android.Support.Core.Utils" Version="25.4.0.2" />

    <Reference Include="Mono.Android" />

    <Reference Include="System.Numerics" />

    <Reference Include="System.Numerics.Vectors" />

    <Compile Include="**\*.android.cs" />

  </ItemGroup>

  <ItemGroup Condition=" $(TargetFramework.StartsWith('Xamarin.iOS'))">

    <Reference Include="System.Numerics" />

    <Reference Include="System.Numerics.Vectors" />

    <Compile Include="**\*.ios.cs" />

  </ItemGroup>


  <Import Project="$(MSBuildSDKExtrasTargets)" Condition="Exists('$(MSBuildSDKExtrasTargets)')" />

  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />

</Project>

 剩下的事情,就是针对不同平台作定义了
      如Kinfey.ios.cs

using System;

namespace DNDemo.Lib

{

    public static partial class Kinfey

    {

        internal static string Check(){

            return "iOS";

        }

    }

}

 如Kinfey.android.cs

using System;

namespace DNDemo.Lib

{

    public static partial class Kinfey

    {

        internal static string Check()

        {

            return "Android";

        }

    }

}

而Kinfey.netstandard.cs

using System;

namespace DNDemo.Lib

{

    public static partial class Kinfey

    {

        internal static string Check() => throw new NotImplementedException();

    }

}

最后暴露的接口在Kinfey.shared.cs

using System;

namespace DNDemo.Lib

{

    public static partial class Kinfey

    {

        public static string CheckInfo(){

            return Check();

        }

    }

}

这样你就可以进行编译了,在Windows上你直接用Visual Studio 编译即可,在macOS上你需要编译就需要用命令行了(请高人指点下,我不知道为啥VS for mac不能build跨平台的.NET Stanard......),首先你得restore , 接着执行
msbuild DNDemo.Lib.csproj /p:Configuration=Debug
这个时候,你就会得到四个库.net standard 1.0 / .net standard 2.0 / ios / android 。找个项目调用一下,结果如下:

      640?wx_fmt=png 

      赠送源码一份:(点击下载)
      最后Xamarin的第三方库在国外有不少,但国内还是相对较少,希望各位爱好者都贡献一下,为这个技术落地贡献一份力量。

原文地址: https://blog.csdn.net/kinfey/article/details/80218291


 

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

640?wx_fmt=jpeg


这篇关于从Xamarin.Essentials谈Xamarin库的封装的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/357598

相关文章

SpringBoot中封装Cors自动配置方式

《SpringBoot中封装Cors自动配置方式》:本文主要介绍SpringBoot中封装Cors自动配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录SpringBoot封装Cors自动配置背景实现步骤1. 创建 GlobalCorsProperties

Java导入、导出excel用法步骤保姆级教程(附封装好的工具类)

《Java导入、导出excel用法步骤保姆级教程(附封装好的工具类)》:本文主要介绍Java导入、导出excel的相关资料,讲解了使用Java和ApachePOI库将数据导出为Excel文件,包括... 目录前言一、引入Apache POI依赖二、用法&步骤2.1 创建Excel的元素2.3 样式和字体2.

JAVA封装多线程实现的方式及原理

《JAVA封装多线程实现的方式及原理》:本文主要介绍Java中封装多线程的原理和常见方式,通过封装可以简化多线程的使用,提高安全性,并增强代码的可维护性和可扩展性,需要的朋友可以参考下... 目录前言一、封装的目标二、常见的封装方式及原理总结前言在 Java 中,封装多线程的原理主要围绕着将多线程相关的操

C++实现封装的顺序表的操作与实践

《C++实现封装的顺序表的操作与实践》在程序设计中,顺序表是一种常见的线性数据结构,通常用于存储具有固定顺序的元素,与链表不同,顺序表中的元素是连续存储的,因此访问速度较快,但插入和删除操作的效率可能... 目录一、顺序表的基本概念二、顺序表类的设计1. 顺序表类的成员变量2. 构造函数和析构函数三、顺序表

Go语言利用泛型封装常见的Map操作

《Go语言利用泛型封装常见的Map操作》Go语言在1.18版本中引入了泛型,这是Go语言发展的一个重要里程碑,它极大地增强了语言的表达能力和灵活性,本文将通过泛型实现封装常见的Map操作,感... 目录什么是泛型泛型解决了什么问题Go泛型基于泛型的常见Map操作代码合集总结什么是泛型泛型是一种编程范式,允

JavaSE——封装、继承和多态

1. 封装 1.1 概念      面向对象程序三大特性:封装、继承、多态 。而类和对象阶段,主要研究的就是封装特性。何为封装呢?简单来说就是套壳屏蔽细节 。     比如:对于电脑这样一个复杂的设备,提供给用户的就只是:开关机、通过键盘输入,显示器, USB 插孔等,让用户来和计算机进行交互,完成日常事务。但实际上:电脑真正工作的却是CPU 、显卡、内存等一些硬件元件。

哈希表的封装和位图

文章目录 2 封装2.1 基础框架2.2 迭代器(1)2.3 迭代器(2) 3. 位图3.1 问题引入3.2 左移和右移?3.3 位图的实现3.4 位图的题目3.5 位图的应用 2 封装 2.1 基础框架 文章 有了前面map和set封装的经验,容易写出下面的代码 // UnorderedSet.h#pragma once#include "HashTable.h"

封装MySQL操作时Where条件语句的组织

在对数据库进行封装的过程中,条件语句应该是相对难以处理的,毕竟条件语句太过于多样性。 条件语句大致分为以下几种: 1、单一条件,比如:where id = 1; 2、多个条件,相互间关系统一。比如:where id > 10 and age > 20 and score < 60; 3、多个条件,相互间关系不统一。比如:where (id > 10 OR age > 20) AND sco

Java封装构造方法

private/public的分装 被public修饰的成员变量或者是成员方法,可以被类的调用对象直接使用 而private修饰的成员变量和方法,不能被类的调用对象使用 例如: 可以看到我们是不能在main方法中直接调用被private修饰的变量 当然我们可以在我们定义的TestMode类中可以定一个方法show,然后在调用show方法实现 这里我们可以清楚了解 private 不光可以修

C++数据结构重要知识点(5)(哈希表、unordered_map和unordered_set封装)

1.哈希思想和哈希表 (1)哈希思想和哈希表的区别 哈希(散列、hash)是一种映射思想,本质上是值和值建立映射关系,key-value就使用了这种思想。哈希表(散列表,数据结构),主要功能是值和存储位置建立映射关系,它通过key-value模型中的key来定位数组的下标,将value存进该位置。 哈希思想和哈希表数据结构这两个概念要分清,哈希是哈希表的核心思想。 (2)unordered