Xamarin.Forms: Forms.Context is obsolete

后端 未结 2 2037
栀梦
栀梦 2020-11-28 11:24

The new obsolete warning in Xamarin.Forms 2.5 really puzzled me. What context should I be using in Dependency Services, for example, to call GetSystemService()?

Shou

相关标签:
2条回答
  • 2020-11-28 11:46

    I was having the same issue with several Dependency Services

    The simplest solution

    In a lot of cases for Single Activity Applications

    Xamarin.Forms.Forms.Context
    

    Can be replaced with

    Android.App.Application.Context
    

    The Background in more detail

    Android.App.Application.Context returns the global Application Context of the current process tied to the lifecycle of the Application, as apposed to an Activity context.

    A typical example of using the Application context is for starting an Activity e.g.

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

    The general rule of thumb is to use the current Activity Context, unless you need to save a reference to a context from an object that lives beyond your Activity. In which case use the Application context

    Why did Forms.Context go obsolete?

    Xmarin.Forms 2.5 introduced a new "Forms embedding" feature, which can embed Forms pages into Xamarin.iOS / Xamarin.Android apps. However, since Xamarin.Android apps can use multiple Activities, seemingly there was a danger of Xamarin.Android users calling Forms.Context and in turn getting a reference to the MainActivity, which has the potential cause problems.

    The work around

    Inside a Renderer you now get a reference to the view’s context which is passed into the constructor.

    With any other class you are faced with the issue of how to get the Activity Context. In a single Activity application (in most cases) the Application.Context will work just fine.

    However to get the current Activity Context in a Multiple Activity Application you will need to hold a reference to it. The easiest and most reliable way to do this is via a class that implements the Application.IActivityLifecycleCallbacks Interface.

    The main idea is to keep a reference of the Context when an Activity is created, started, or resumed.

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

    With the above approach, single Activity Applications and multiple Activity Applications can now always have access to the Current/Local Activity Context. e.g instead of relying on the global context

    Android.App.Application.Context 
    
    // or previously
    
    Xamarin.Forms.Forms.Context
    

    Can now be replaced with

    MainApplication.ActivityContext
    

    Example call in a Dependency Service

    if (MainApplication.ActivityContext!= null)
    {
        versionNumber = MainApplication.ActivityContext
                           .PackageManager
                           .GetPackageInfo(MainApplication.ActivityContext.PackageName, 0)
                           .VersionName;
    }
    

    Additional Resources

    Android.App.Application.IActivityLifecycleCallbacks

    registerActivityLifecycleCallbacks

    0 讨论(0)
  • 2020-11-28 11:52

    In the latest scaffold of a new Xamarin Forms solution the CrossActivityPlugin (https://github.com/jamesmontemagno/CurrentActivityPlugin) is referenced in the Android project. So you can use

    CrossCurrentActivity.Current.Activity.StartActivity(myIntent)

    0 讨论(0)
提交回复
热议问题