简体   繁体   English

在 Xamarin.Forms 中编写特定于设备平台的代码

[英]Write device platform specific code in Xamarin.Forms

I have the following Xamarin.Forms.ContentPage class structure我有以下Xamarin.Forms.ContentPage类结构

public class MyPage : ContentPage
{
    public MyPage()
    {
        //do work to initialize MyPage 
    }

    public void LogIn(object sender, EventArgs eventArgs)
    {
        bool isAuthenticated = false;
        string accessToken = string.Empty;

        //do work to use authentication API to validate users

        if(isAuthenticated)
        {
            //I would to write device specific code to write to the access token to the device
            //Example of saving the access token to iOS device
            NSUserDefaults.StandardUserDefaults.SetString(accessToken, "AccessToken");

            //Example of saving the access token to Android device
            var prefs = Application.Context.GetSharedPreferences("MySharedPrefs", FileCreationMode.Private);
            var prefsEditor = prefs.Edit();

            prefEditor.PutString("AccessToken", accessToken);
            prefEditor.Commit();
        }
    }
}

I would like to write platform specific code in the MyPage LogIn method to save the access token based on which device OS they are using my application on.我想在MyPage LogIn方法中编写特定于平台的代码,以根据他们使用我的应用程序的设备操作系统保存访问令牌。

How do I only run device specific code when the user uses my application on their device?当用户在他们的设备上使用我的应用程序时,我如何只运行设备特定的代码?

This is a scenario which is easily resolved with dependency injection.这是一个可以通过依赖注入轻松解决的场景。

Have a interface with the desired methods on your shared or PCL code, like:在您的共享或 PCL 代码上有一个包含所需方法的接口,例如:

public interface IUserPreferences 
{
    void SetString(string key, string value);
    string GetString(string key);
}

Have a property on your App class of that interface:在该接口的App类上有一个属性:

public class App 
{
    public static IUserPreferences UserPreferences { get; private set; }

    public static void Init(IUserPreferences userPreferencesImpl) 
    {
        App.UserPreferences = userPreferencesImpl;
    }

    (...)
}

Create platform-specific implementations on your target projects:在您的目标项目上创建特定于平台的实现:

iOS: IOS:

public class iOSUserPreferences : IUserPreferences 
{
    public void SetString(string key, string value)
    {
        NSUserDefaults.StandardUserDefaults.SetString(key, value);
    }

    public string GetString(string key)
    {
        (...)
    }
}

Android:安卓:

public class AndroidUserPreferences : IUserPreferences
{
    public void SetString(string key, string value)
    {
        var prefs = Application.Context.GetSharedPreferences("MySharedPrefs", FileCreationMode.Private);
        var prefsEditor = prefs.Edit();

        prefEditor.PutString(key, value);
        prefEditor.Commit();
    }

    public string GetString(string key)
    {
        (...)
    }
}

Then on each platform-specific project create an implementation of IUserPreferences and set it using either App.Init(new iOSUserPrefernces()) and App.Init(new AndroidUserPrefernces()) methods.然后在每个特定于平台的项目上创建IUserPreferences的实现,并使用App.Init(new iOSUserPrefernces())App.Init(new AndroidUserPrefernces())方法设置它。

Finally, you could change your code to:最后,您可以将代码更改为:

public class MyPage : ContentPage
{
    public MyPage()
    {
        //do work to initialize MyPage 
    }

    public void LogIn(object sender, EventArgs eventArgs)
    {
        bool isAuthenticated = false;
        string accessToken = string.Empty;

        //do work to use authentication API to validate users

        if(isAuthenticated)
        {
            App.UserPreferences.SetString("AccessToken", accessToken);
        }
    }
}

Xamarin.Forms 2.3.4 introduced a new method for this: Xamarin.Forms 2.3.4 为此引入了一种新方法:

if (Device.RuntimePlatform == Device.Android)
{
    // Android specific code
}
else if (Device.RuntimePlatform == Device.iOS)
{
    // iOS specific code
}
else if (Device.RuntimePlatform == Device.UWP)
{
    // UWP specific code
}

There are also other platforms to choose from, you can type in Device.还有其他平台可供选择,您可以输入Device. in Visual Studio and it will show you the options.在 Visual Studio 中,它将显示选项。

There are multiple answers, depending on what you want to achieve, and the kind of project you have:有多种答案,具体取决于您想要实现的目标以及您拥有的项目类型:

Execute different Xamarin.Forms code on different platforms.在不同平台上执行不同的Xamarin.Forms代码。
Use this eg if you want different font sizes on different platforms:例如,如果您希望在不同平台上使用不同的字体大小,请使用此命令:

label.Font = Device.OnPlatform<int> (12, 14, 14);

Execute platform specific code in a shared (PCL) project The common pattern is to use DI (dependency injection) for this.在共享 (PCL) 项目中执行平台特定代码常见模式是为此使用 DI(依赖注入)。 Xamarin.Forms provides a simple DependencyService for this, but use whatever you want. Xamarin.Forms提供了一个简单的DependencyService ,但可以使用任何你想要的。

Execute platform specific code in shared (Shared Asset Project) project As the code is compiled per platform, you can wrap your platform specific code in #if __PLATFORM__ #endif and have all the code in the same file.在共享(共享资产项目)项目中执行平台特定代码由于代码是按平台编译的,您可以将平台特定代码包装在#if __PLATFORM__ #endif并将所有代码放在同一个文件中。 The platform project should define __IOS__ , __ANDROID__ and __WINDOWS_PHONE__ .平台项目应定义__IOS____ANDROID____WINDOWS_PHONE__ Note that a shared asset project containing Xaml and code won't work well for iOS on Xamarin.Studio , and that having compiler directives makes your code harder to read and to test.请注意,包含Xaml和代码的共享资产项目不适用于Xamarin.Studio iOS,并且具有编译器指令会使您的代码更难阅读和测试。

This seems less about Xamarin.Forms and more about using defaults in a PCL.这似乎与Xamarin.Forms而更多地与在 PCL 中使用默认值有关。 Check out James Montemagno's github repo for doing cross-platform defaults.查看James Montemagno 的 github repo以进行跨平台默认设置。

Then just call his static methods for setting/retrieving.然后只需调用他的静态方法进行设置/检索。 The nuget package is Xam.Plugins.Settings . nuget 包是Xam.Plugins.Settings

It can be used like this:它可以像这样使用:

using Refractored.Xam.Settings;

... ...

CrossSettings.Current.AddOrUpdateValue("AccessToken", accessToken);
var value = CrossSettings.Current.GetValueOrDefault<string>("AccessToken");

Xamarin.Forms has a built-in dependency injector if you take a look at their guide in the developer area of their website ( http://developer.xamarin.com/guides/cross-platform/xamarin-forms/dependency-service/ ) Xamarin.Forms 有一个内置的依赖注入器,如果你在他们的网站 ( http://developer.xamarin.com/guides/cross-platform/xamarin-forms/dependency-service/ )

There's also a wonderful library you can pull from NuGet/Github ( https://github.com/aritchie/acr-xamarin-forms ) that will handle the storage requirement you are looking for... take a look at the Settings service in there, it will even handle serialization of more complex objects.还有一个很棒的库,您可以从 NuGet/Github ( https://github.com/aritchie/acr-xamarin-forms ) 中提取,它将处理您正在寻找的存储要求......查看设置服务在那里,它甚至可以处理更复杂对象的序列化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM