12/08/2018, 17:11

Sử dụng DependencyService trong Xamarin Form

1. Giới thiệu Như đã biết tầng share-code là nơi chứa các code không phụ thuộc vào nền tảng, đó là code chung giữa các platform: iOS, Android, Windows Phone. Chính vì thế rất khó để viết các đoạn code đặc thù của từng nền tảng. Thay vào đó, chúng ta viết các đoạn code đặc thù cho riêng từng ...

1. Giới thiệu

Như đã biết tầng share-code là nơi chứa các code không phụ thuộc vào nền tảng, đó là code chung giữa các platform: iOS, Android, Windows Phone. Chính vì thế rất khó để viết các đoạn code đặc thù của từng nền tảng. Thay vào đó, chúng ta viết các đoạn code đặc thù cho riêng từng platform, nhưng lại có thể "invoke" nó trên tầng share-code bằng DependencyService. Bản chất của c là interface và gọi các phần code đặc thù theo nền tảng đã implement interface đó.

Vậy DependencyService hoạt động thế nào? Xamarin Form cần 3 thành phần sau để DependencyService có thể hoạt động:

  • Interface: Những function yêu cầu được định nghĩa ở đây, trong phần share-code
  • Implementation Per Platform: Phần code implement cho interface đó, và được viết cho từng nền tảng: iOS, Android, Windows Phone. Tuy nhiên các class implement interface đó, cần phải được đăng kí, để Dependency Service có thể biết được, và điều hướng ("invoke") đến các hàm đó trong run time.
  • Call to DependencyService: Dependency Service chỉ có thể được gọi ở tầng share-code. Mỗi plaftorm cần phải implement tất cả các hàm của interface đó nếu muốn function hoạt động đúng trên nền tảng mình mong muốn.

Cấu trúc của Dependency Service như hình bên dưới:

2. Interface

Interface là nơi chúng ta thiết kế, định nghĩa cách chúng ta tương tác với các platform. Ví dụ bên dưới là một định nghĩa interface, cho phép phát âm một text được truyền vào, tuy nhiên phần implement được "vứt" xuống cho từng platform thực hiện.

using System;
namespace PhoneCall
{
    public interface IPhoneCall
    {
        void MakePhoneCall(string phoneNumber);
    }
}

3.Implementation per Platform

Sau khi đã có interface, chúng ta cầm implement các function cho interface đó hướng đến từng nền tảng mà chúng ta nhắm đến. Ví dụ dưới là một class thực thi interface cho nền tảng iOS:

using System;
using AVFoundation;
using Xamarin.Forms;
using UIKit;
using Foundation;


[assembly: Dependency(typeof(PhoneCall.iOS.PhoneCall_iOS))]
namespace PhoneCall.iOS
{
    public class PhoneCall_iOS : IPhoneCall
    {
        public PhoneCall_iOS()
        {
        }

        public void MakePhoneCall(string phoneNumber)
        {
            var phoneSchemal = "telprompt://" + phoneNumber;
            var url = new NSUrl(phoneSchemal);
            if (UIApplication.SharedApplication.CanOpenUrl(url))
            {
                UIApplication.SharedApplication.OpenUrl(url);
            }
        }

    }
}

Lứu ý mỗi class thực thi interface cần phải có một constructor mặc định, đảm bảo sao cho Dependency Service có thể tự tạo đối tượng cho class đó.

3. Registration

Mỗi một class mà thực thi interface đó, cần phải được đăng kí với Dependency Service, ví dụ bên dưới là đoạn code đăng kí class PhoneCall_iOS , phía trên phần khai báo class.

[assembly: Dependency(typeof(PhoneCall.iOS.PhoneCall_iOS))]
namespace PhoneCall.iOS

4. Call to DependencyService

Sau khi tất cả các nền tảng đã được thực thi interface trên, chúng ta có thể invoke các phần thực thi đó, cho từng nền tảng tại run time.

 phoneCall.Clicked += (sender, e) =>
            {
                String phoneNumber = phoneText.Text;
                DependencyService.Get<IPhoneCall>().MakePhoneCall(phoneNumber);
            };

Đơn giản có thể thấy, đoạn code DependencyService.Get<T> tìm đến phần code thực thì interface T ứng với nền tảng đang chạy.

5. Solution Structure

Chúng ta có thể thấy răng, sulution được chia thành 3 project riêng biệt:

  • PhoneCall: đây là project chứa phần share-code giữa tất cả nền tảng.
using System;
using Xamarin.Forms;

namespace PhoneCall
{
    public class MainPage : ContentPage
    {
        public MainPage()
        {
            var phoneText = new Entry()
            {
                VerticalOptions = LayoutOptions.Center,
                HorizontalOptions = LayoutOptions.Center,
                Margin = new Thickness(50),
                HeightRequest = 50,
                WidthRequest = 200,
                Placeholder = "input phone number",
                Keyboard = Keyboard.Telephone
            };

            var phoneCall = new Button
            {
                Text = "MAKE PHONE CALL",
                VerticalOptions = LayoutOptions.Center,
                HorizontalOptions = LayoutOptions.Center,
                Margin = new Thickness(10, 10, 10, 10),
                WidthRequest = 200,
                BorderWidth = 1,
                BorderColor = Color.Blue,
                TextColor = Color.Red
            };
            phoneCall.Clicked += (sender, e) =>
            {
                var phoneNumber = phoneText.Text;
                DependencyService.Get<IPhoneCall>().MakePhoneCall(phoneNumber);
            };

            var mainContent = new StackLayout()
            {
                Orientation = StackOrientation.Vertical,

            };
            mainContent.Children.Add(phoneText);
            mainContent.Children.Add(phoneCall);

            Content = mainContent;
        }
    }
}

Để ý đến đoạn code `  DependencyService.Get<IPhoneCall>().MakePhoneCall(phoneNumber);` đây chính là việc chúng ta sử dụng DependencyService gọi phần thực thị của các nền tảng trên tầng code-share.

Ở MainPage.cs chúng ta invoke phần code thực thi interface IPhoneCall của từng nền tảng.

  • PhoneCall.iOS
using System;
using AVFoundation;
using Xamarin.Forms;
using UIKit;
using Foundation;


[assembly: Dependency(typeof(PhoneCall.iOS.PhoneCall_iOS))]
namespace PhoneCall.iOS
{
    public class PhoneCall_iOS : IPhoneCall
    {
        public PhoneCall_iOS()
        {
        }

        public void MakePhoneCall(string phoneNumber)
        {
            var phoneSchemal = "telprompt://" + phoneNumber;
            var url = new NSUrl(phoneSchemal);
            if (UIApplication.SharedApplication.CanOpenUrl(url))
            {
                UIApplication.SharedApplication.OpenUrl(url);
            }
        }

    }
}

Phần quạn trong nhất trong project này là class PhoneCall_iOS, đây là class thực thi interface IPhoneCall, và được viết bằng code được thù của iOS.

  • PhoneCall.Android
using System;
using Xamarin.Forms;
using Android.Content;
using Android.OS;
using Xamarin.Android;
using Android.App;
using PhoneCall.Droid;

[assembly: Dependency(typeof(PhoneCall_Android))]
namespace PhoneCall.Droid
{
    public class PhoneCall_Android : IPhoneCall
    {
        public PhoneCall_Android()
        {
        }

        public void MakePhoneCall(string phoneNumber)
        {
            Intent callIntent = new Intent(Intent.ActionCall);
            callIntent.SetData(Android.Net.Uri.Parse("tel:" + phoneNumber));
            Forms.Context.StartActivity(callIntent);
        }

    }
}

Cũng giống iOS thì đoạn code trên được viết ở trong project Android, và thực thi interface IPhoneCall trên nền tảng Android.

Toàn bộ source code của project các bạn có thể lấy tại link sau: https://github.com/tungvt01/xamarinFormPhoneCallDemo

0