Xamarin.Forms:Forms.Context 已过时

Posted

技术标签:

【中文标题】Xamarin.Forms:Forms.Context 已过时【英文标题】:Xamarin.Forms: Forms.Context is obsolete 【发布时间】:2018-05-01 10:15:36 【问题描述】:

Xamarin.Forms 2.5 中新的过时警告确实让我感到困惑。 例如,我应该在 Dependency Services 中使用什么上下文来调用 GetSystemService()?

我应该将 xamarin 表单初始化时所针对的活动上下文存储在静态字段中吗?

我应该重写android Application 类并使用它的上下文吗?

我应该在活动创建时调用 GetSystemService 并将其保存在某处吗?

【问题讨论】:

【参考方案1】:

我遇到了几个Dependency Services同样的问题

最简单的解决方案

单活动应用程序

在很多情况下
Xamarin.Forms.Forms.Context

可以替换为

Android.App.Application.Context

更详细的背景

Android.App.Application.Context 返回与应用程序生命周期相关联的当前进程的全局应用程序上下文,与 Activity 上下文相对。

使用 Application 上下文的典型示例是启动 Activity,例如

Android.App.Application.Context.StartActivity(myIntent);

一般的经验法则是使用当前的活动上下文,除非你需要 保存对超出您的对象的上下文的引用 活动。在这种情况下使用应用程序上下文

为什么 Forms.Context 过时了?

Xmarin.Forms 2.5 引入了新的“表单嵌入”功能,可以将表单页面嵌入到 Xamarin.ios / Xamarin.Android 应用中。但是,由于 Xamarin.Android 应用程序可以使用多个活动,因此Xamarin.Android 用户似乎存在调用Forms.Context 并反过来获得对MainActivity 的引用的危险,这可能会导致问题。

解决方法

在渲染器中,您现在获得了对视图上下文的引用,该引用被传递到构造函数中。

对于任何其他类,您都面临如何获取活动上下文的问题。在单个 Activity 应用程序(大多数情况下)Application.Context 可以正常工作。

但是,要在多活动应用程序中获取当前活动上下文,您需要持有对它的引用。最简单、最可靠的方法是通过实现Application.IActivityLifecycleCallbacks 接口的class

主要思想是在 Activity 时保持 Context 的引用 被创建、启动或恢复。

[Application]
public partial class MainApplication : Application, Application.IActivityLifecycleCallbacks

   internal static Context ActivityContext  get; private set; 

   public MainApplication(IntPtr handle, JniHandleOwnership transfer) : base(handle, transfer)  

   public override void OnCreate()
   
      base.OnCreate();
      RegisterActivityLifecycleCallbacks(this);
       

   public override void OnTerminate()
   
      base.OnTerminate();
      UnregisterActivityLifecycleCallbacks(this);
     

   public void OnActivityCreated(Activity activity, Bundle savedInstanceState)
   
      ActivityContext = activity;
      

   public void OnActivityResumed(Activity activity)
   
      ActivityContext = activity;
   

   public void OnActivityStarted(Activity activity)
   
      ActivityContext = activity;
   

   public void OnActivityDestroyed(Activity activity)    
   public void OnActivityPaused(Activity activity)  
   public void OnActivitySaveInstanceState(Activity activity, Bundle outState)  
   public void OnActivityStopped(Activity activity)  

通过上述方法,单个 Activity 应用程序多个 Activity 应用程序现在始终可以访问当前/本地 Activity 上下文。例如,而不是依赖于全局上下文

Android.App.Application.Context 

// or previously

Xamarin.Forms.Forms.Context

现在可以替换为

MainApplication.ActivityContext

依赖服务中的示例调用

if (MainApplication.ActivityContext!= null)

    versionNumber = MainApplication.ActivityContext
                       .PackageManager
                       .GetPackageInfo(MainApplication.ActivityContext.PackageName, 0)
                       .VersionName;


其他资源

Android.App.Application.IActivityLifecycleCallbacks

registerActivityLifecycleCallbacks

【讨论】:

这似乎不适用于 CustomTabsActivityManager(Android.App.Application.Context as Activity)。有什么选择吗? @Shubhan 你不能只传入父活动吗? 在我的情况下,我没有用于打开 Web 链接的接口实现。不能发送设备特定的参数,在这种情况下是 Activity。我正在查看的选项是我的 Activity 上的静态对象,这是糟糕的设计【参考方案2】:

在新 Xamarin Forms 解决方案的最新脚手架中,Android 项目中引用了 CrossActivityPlugin (https://github.com/jamesmontemagno/CurrentActivityPlugin)。所以你可以使用

CrossCurrentActivity.Current.Activity.StartActivity(myIntent)

【讨论】:

以上是关于Xamarin.Forms:Forms.Context 已过时的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin.Forms 手势密码实现

Xamarin.Forms 和 Xamarin Native 有啥区别? [关闭]

如何使用 Xamarin.Forms.Maps(无 Xamarin.Forms.GoogleMaps)在地图中应用样式或更改颜色

Xamarin Forms Prism:prism ResourceDictionary 中已存在具有键“Xamarin.Forms.NavigationPage”的资源

Xamarin.Forms.Forms.Init(e) Onlaunched 中的 FileNotFoundExeception

如果调用方未使用 Xamarin.Forms,Xamarin 依赖项服务能否正常工作?