Xamarin.Forms:Forms.Context 已过时

Xamarin.Forms: Forms.Context is obsolete

提问人:Anton Duzenko 提问时间:11/17/2017 更新时间:6/27/2018 访问量:29038

问:

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

我是否应该在静态字段中存储初始化 xamarin 窗体所针对的活动的上下文?

我应该覆盖 android Application 类并使用其 Context 吗?

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

xamarin.forms

评论


答:

89赞 TheGeneral 11/18/2017 #1

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

最简单的解决方案

在很多情况下,对于单个活动应用程序

Xamarin.Forms.Forms.Context

可以替换为

Android.App.Application.Context

更详细的背景

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

使用应用程序上下文的一个典型示例是启动活动,例如

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

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

为什么 Forms.Context 过时了?

Xmarin.Forms 2.5 引入了新的“窗体嵌入”功能,该功能可以将窗体页面嵌入到 Xamarin.iOS/Xamarin.Android 应用中。但是,由于 Xamarin.Android 应用可以使用多个活动,因此似乎存在用户调用并反过来获取对 的引用的危险,这可能会导致问题。Xamarin.AndroidForms.ContextMainActivity

解决方法

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

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

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

主要思想是在活动时保留上下文的引用 已创建、启动或恢复。

[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) { }
}

使用上述方法,单个活动应用程序和多个活动应用程序现在始终可以访问当前/本地活动上下文。例如,而不是依赖全球环境

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.IActivityLifecycle回调

registerActivityLifecycle回调

评论

0赞 Shubhan 12/10/2017
这似乎不适用于 CustomTabsActivityManager(Android.App.Application.Context as Activity)。有什么选择吗?
0赞 TheGeneral 12/11/2017
@Shubhan你不能直接传入父活动吗?
1赞 Shubhan 12/11/2017
就我而言,我没有用于打开 Web 链接的界面实现。无法发送特定于设备的参数,在这种情况下是活动。我正在查看的选项是我的活动上的静态对象,这是糟糕的设计
3赞 Guido Neele 6/1/2018 #2

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

CrossCurrentActivity.Current.Activity.StartActivity(myIntent)