Xamarin.Forms學習之Platform-specific API和文件操作


  這篇文章的分享原由是由於上篇關於Properties的保存不了,調用SavePropertiesAsync()方法也不行,所以我希望通過操作文件的方式保存我的需要的數據,然后我看了一下電子書中的第二十章和需要相關知識的第九章,這篇文章中的內容則是我學習這兩章的一點記錄和分享,還是那樣,有錯請留言指正,謝謝!

  不同的平台存在着一些特定的API,通過在電子書中兩章的學習,實踐一下如何調用這些API和將這些API封裝成公共的庫,供以后的項目調用。以一個顯示平台信息的小實例開始做一個簡單的演示,其運行效果如下:

  

  C#代碼如下(就是電子書中的實例,只不過只有IOS和Android的):

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="App3.Views.DisplayModelAndVersion">
  <StackLayout Padding="20">
        <StackLayout VerticalOptions="CenterAndExpand">
            <Label Text="Device Model:" />

            <ContentView Padding="10, 0, 0, 0">
                <Label x:Name="modelLabel"
                       FontSize="Large"
                       FontAttributes="Bold" />
            </ContentView>
        </StackLayout>

        <StackLayout VerticalOptions="CenterAndExpand">
            <Label Text="Operating System Version:" />

            <ContentView Padding="10, 0, 0, 0">
                <Label x:Name="versionLabel"
                       FontSize="Large"
                       FontAttributes="Bold" />
            </ContentView>
        </StackLayout>
    </StackLayout>
</ContentPage>



#if __IOS__
using UIKit;

#elif __ANDROID__
using Android.OS;
#endif

namespace App3.Views
{
public partial class DisplayModelAndVersion: ContentPage { public PlatInfoSap1Page () { InitializeComponent (); #if __IOS__ UIDevice device = new UIDevice(); modelLabel.Text = device.Model.ToString(); versionLabel.Text = String.Format("{0} {1}", device.SystemName, device.SystemVersion); #elif __ANDROID__ modelLabel.Text = String.Format("{0} {1}", Build.Manufacturer, Build.Model); versionLabel.Text = Build.VERSION.Release.ToString(); #endif } } }

  記得在程序集中添加對Mono.Android和Xamarin.IOS的引用。

  也許只有這一個,你看不出很麻煩,但是如果你要調用更多的特定的API,那么可以想見,你的代碼中將會有許多的“#if __IOS__ xxxxx  #elif __ANDROID__ xxxxxx #endif”這樣的代碼,那能不能把這些特定的API封裝在其相應的平台,實現分平台的調用呢,當然是可以的。。。。。。我就不寫其他的廢話,就是通過DependencyService來實現的,直接上代碼:

  

  添加如上圖所的接口和類(Sorry,下面那個箭頭搞錯了)

    public interface IPlatformInfo
    {
        string GetModel();

        string GetVersion();
    }


    public class PlatformInfo
    {
        IPlatformInfo fileHelper = DependencyService.Get<IPlatformInfo>();

        public string GetModel()
        {
            return fileHelper.GetModel();
        }

        public string GetVersion()
        {
            return fileHelper.GetVersion();
        }
    }


[assembly: Dependency(typeof(App3.Droid.PlatformInfo))]
namespace App3.Droid
{
    class PlatformInfo : IPlatformInfo
    {
        public string GetModel()
        {
            return string.Format("{0} {1}", Build.Manufacturer, Build.Model);
        }

        public string GetVersion()
        {
            return Build.VERSION.Release;
        }
    }
}

   記住DependencyService和Dependency的命名空間是Xamarin.Froms,我開始沒注意就被坑了。IOS的代碼沒有什么變化,就是命名空間變了,就不貼出來了,我也沒寫。。。

  當你看到“assembly: Dependency”這個的時候,你也許就聯想到了反射--是的,就是通過反射。建議大家在實現相關的功能是首先使用DependencyService,至於原因我就不用我蹩腳的英語給大家翻譯了,直接上原文:

DependencyService is not the only way to implement platform-specific calls in a PCL. Adventurous developers might want to use dependency-injection techniques to configure the PCL to make calls into the platform projects. But DependencyService is very easy to use, and it eliminates most reasons to use a Shared Asset Project in a Xamarin.Forms application.

  

  現在我們繼續說說如何把這些設置成公共的庫,便於以后的項目調用,其實很簡單,就像我們新建一個Xamarin.Froms項目一樣,新建一個Xamarin.Platfrom.Tools項目,然后把上面PlatformInfo相關的類和接口再寫一遍,建議再添加一個Init的cs文件,代碼中不用實現什么具體的東西,其功能就是確保dll正確的加載了。

 

  對於文件的操作,電子書中有個小標題“Good news and bad news”,當中的主要內容就是告訴大家操作文件的是System.IO命名空間(該命名空間下還有個FileInfo類)下的File類在Android和IOS是可以共用的,但是在Windows的三個平台不行,最明顯的一個區別就是Windows的三個平台的文件操作是異步的,做過WP開發的應該知道。鑒於目前的移動端的情形,和使用Xamarin開發的主要需求,那個”bad news“我們基本可以忽略了(開發Windows的還是用UWP吧)。

  在移動端,基本上都包含一些基本的文件夾,比如Pictures、Music等這些都是公共的,而APP所訪問的文件夾和文件還有一個限制,在WP開發中有個名詞叫“隔離存儲”或者“獨立存儲”,IOS和Android我並沒有太多的接觸,但這方面應該都是大體相同的,所以每個應用程序都除了能訪問前面說的公共的文件夾和文件之外,都只能訪問自己的程序“域”下面的文件夾和文件,做過移動開發或者了解移動開發的應該都知道。對於這些文件夾,Xamarin定義一個SpecialFolder的枚舉,其中的MyDocuments就是我們自己的APP才能訪問的。通過下面的示例繼續:

  

  添加如上圖所示的紅色箭頭的類和接口,代碼如下(限於文章的篇幅,我就不貼整個代碼,只上GetFiles的):  

namespace App3.TestFile
{
    public interface IFileHelper
    {        IEnumerable<string> GetFiles();
} } namespace App3.TestFile { public class FileHelper { IFileHelper fileHelper = DependencyService.Get<IFileHelper>(); public IEnumerable<string> GetFiles() { return fileHelper.GetFiles(); }
} }

[assembly: Dependency(typeof(App3.Droid.FileHelper))]
namespace App3.Droid
{
    class FileHelper : IFileHelper
    {

        public IEnumerable<string> GetFiles()
        {

       // Sort the filenames.
            //string path = GetDocsFolder();
            //IEnumerable<string> filenames =
            //    from filepath in new List<string> { path }
            //    select filepath;

            IEnumerable<string> filenames =
                from filepath in Directory.EnumerateFiles(GetDocsFolder())
                select filepath;

            return filenames;
        }

        string GetDocsFolder()
        {
            return Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
        }
    }
}

 

  至於XAML呢么就是一個簡單的ListView,這個倒沒什么說的。大家自己試一試吧。

  這里的文件操作能滿足我們許多的需求了,但是有時候我們在項目中添加一個圖片、文件或者其他的,該怎么辦呢。。。下次再說操作本地文件的事吧!

 

  其實最開始的那版文字描述更通順一些,結果出去吃了飯,回來發現沒有自動保存,而且以前寫的忘了,然后又重新寫了,現在自己讀了一次。。。

  對了,.net core發布了,最近也在摸索,相比於Xamarin,分享和關注的人也更多,學習起來還是很方便的,上周自己也買了一個最便宜的阿里雲的在玩,無語啊,linux也成必學的了,傷心~共勉!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM