web-dev-qa-db-ja.com

Xamarin.Forms:Forms.Contextは廃止されました

Xamarin.Forms 2.5の新しい廃止された警告は、私を本当に困惑させました。 GetSystemService()を呼び出すなど、Dependency Servicesでどのコンテキストを使用する必要がありますか?

Xamarinフォームが初期化されたアクティビティのコンテキストを静的フィールドに保存する必要がありますか?

Android Applicationクラスをオーバーライドし、そのコンテキストを使用する必要がありますか?

アクティビティの作成時にGetSystemServiceを呼び出して、どこかに保存する必要がありますか?

24
Anton Duzenko

私はいくつかのDependency Servicesで同じ問題を抱えていました

最も簡単な解決策

Single Activity Applicationsの多くの場合

Xamarin.Forms.Forms.Context

に置き換えることができます

Android.App.Application.Context

より詳細な背景

Android.App.Application.Contextは、アクティビティコンテキストと同じように、アプリケーションのライフサイクルに関連付けられた現在のプロセスのグローバルアプリケーションコンテキストを返します。

アプリケーションコンテキストを使用する典型的な例は、アクティビティの開始です。

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

一般的な経験則は、アクティビティを超えて存在するオブジェクトからのコンテキストへの参照を保存する必要がない限り、現在のアクティビティコンテキストを使用することです。その場合は、アプリケーションコンテキストを使用します

Forms.Contextが廃止されたのはなぜですか?

Xmarin.Forms 2.5は、フォームページをXamarin.iOS/Xamarin.Androidアプリに埋め込むことができる新しい「フォーム埋め込み」機能を導入しました。ただし、Xamarin.Androidアプリは複数のアクティビティを使用できるため、Xamarin.AndroidユーザーがForms.Contextを呼び出し、次にMainActivityへの参照を取得する危険性があるようです。問題。

回避策

レンダラー内で、コンストラクターに渡されるビューのコンテキストへの参照を取得します。

他のクラスでは、アクティビティコンテキストを取得する方法の問題に直面します。 シングルアクティビティアプリケーション(ほとんどの場合)Application.Contextは正常に機能します。

ただし、Multiple Activity Applicationで現在のアクティビティコンテキストを取得するには、それへの参照を保持する必要があります。これを行う最も簡単で信頼性の高い方法は、Application.IActivityLifecycleCallbacksインターフェイスを実装するclassを使用することです。

主なアイデアは、アクティビティが作成、開始、または再開されるときにコンテキストの参照を保持することです。

[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.IActivityLifecycleCallbacks

registerActivityLifecycleCallbacks

56
TheGeneral

新しいXamarin Formsソリューションの最新の足場では、CrossActivityPlugin( https://github.com/jamesmontemagno/CurrentActivityPlugin )がAndroidプロジェクトで参照されています。使える

CrossCurrentActivity.Current.Activity.StartActivity(myIntent)

1
Guido Neele