Membangun Aplikasi Lintas Platform dengan Xamarin: Perspektif Pengembang Android
Diterbitkan: 2022-03-11Menulis kode sekali dan menggunakannya di berbagai platform telah menjadi impian banyak pengembang perangkat lunak. Meskipun ini telah dimungkinkan untuk beberapa waktu sekarang, selalu datang dengan biaya pemeliharaan, kemudahan pengujian, atau bahkan lebih buruk lagi, pengalaman pengguna yang buruk.
Mengembangkan aplikasi seluler menggunakan SDK asli mungkin merupakan titik awal bagi semua pengembang yang berakar di ranah pengembangan aplikasi desktop. Bahasa pemrograman akan menjadi penghalang bagi beberapa orang: Jika seseorang berpengalaman dalam mengembangkan desktop Java atau aplikasi back-end, pindah ke perusahaan pengembangan aplikasi seluler dan bekerja dengan Android akan terasa jauh lebih mudah daripada memulai dengan Objective-C dari awal untuk iOS.
Saya selalu skeptis terhadap pengembangan aplikasi lintas platform. Kerangka kerja berbasis JavaScript seperti Sencha, Cordova, Titanium, dll. tidak pernah terbukti menjadi pilihan bijak ketika kinerja penting. Kurangnya API dan pengalaman pengguna yang unik diberikan dengan kerangka kerja ini.
Tapi kemudian, saya menemukan Xamarin.
Dalam artikel ini, Anda akan mempelajari bagaimana Anda dapat menggunakan Xamarin untuk berbagi kode di berbagai platform tanpa mengorbankan aspek lain dari pengembangan aplikasi seluler. Artikel ini akan fokus pada Android dan iOS pada khususnya, tetapi Anda dapat menggunakan pendekatan serupa untuk menambahkan dukungan untuk platform lain yang didukung Xamarin.
Apa itu Xamarin?
Xamarin adalah platform pengembangan yang memungkinkan Anda menulis aplikasi lintas platform—namun asli—untuk iOS, Android, dan Windows Phone dalam C# dan .NET.
Xamarin menyediakan pengikatan C# ke API Android dan iOS asli. Ini memberi Anda kekuatan untuk menggunakan semua antarmuka pengguna asli Android dan iOS, pemberitahuan, grafik, animasi, dan fitur telepon lainnya—semuanya menggunakan C#.
Setiap rilis baru Android dan iOS dicocokkan oleh Xamarin, dengan rilis baru yang menyertakan binding untuk API baru mereka.
Port Xamarin dari .NET mencakup fitur seperti tipe data, generik, pengumpulan sampah, kueri terintegrasi bahasa (LINQ), pola pemrograman asinkron, delegasi, dan subset dari Windows Communication Foundation (WCF). Perpustakaan dikelola dengan berlama-lama untuk memasukkan hanya komponen yang direferensikan.
Xamarin.Forms adalah lapisan di atas binding UI lainnya dan Windows Phone API, yang menyediakan pustaka antarmuka pengguna lintas platform sepenuhnya.
Menulis Aplikasi Lintas Platform
Untuk menulis aplikasi lintas platform dengan Xamarin, pengembang harus memilih salah satu dari dua jenis proyek yang tersedia:
- Perpustakaan Kelas Portabel (PCL)
- Proyek Bersama
PCL memungkinkan Anda untuk menulis kode yang dapat dibagikan di antara berbagai platform, tetapi dengan satu batasan. Karena tidak semua .NET API tersedia di semua platform, dengan proyek PCL, Anda akan membatasinya untuk berjalan di platform yang ditargetkan.
Tabel di bawah ini menunjukkan API mana yang tersedia di platform mana:
Fitur | .NET Framework | Aplikasi Toko Windows | cahaya perak | Windows Phone | Xamarin |
---|---|---|---|---|---|
Inti | kamu | kamu | kamu | kamu | kamu |
LINQ | kamu | kamu | kamu | kamu | kamu |
Dapat dimintai permintaan | kamu | kamu | kamu | 7,5+ | kamu |
Serialisasi | kamu | kamu | kamu | kamu | kamu |
Anotasi Data | 4.0.3+ | kamu | kamu | kamu | kamu |
Selama proses pembuatan, PCL dikompilasi menjadi DLL terpisah dan dimuat oleh Mono selama runtime. Implementasi yang berbeda dari antarmuka yang sama dapat disediakan selama runtime.
Di sisi lain, proyek bersama memberi Anda lebih banyak kontrol dengan memungkinkan Anda menulis kode khusus platform untuk setiap platform yang ingin Anda dukung. Kode dalam proyek bersama dapat berisi arahan kompiler yang akan mengaktifkan atau menonaktifkan bagian kode tergantung pada proyek aplikasi mana yang menggunakan kode tersebut.
Tidak seperti PCL, proyek bersama tidak menghasilkan DLL apa pun. Kode tersebut disertakan langsung dalam tugas akhir.
Memberikan Struktur pada Kode Lintas-platform Anda dengan MvvmCross
Kode yang dapat digunakan kembali dapat menghemat uang dan waktu untuk tim pengembangan. Namun, kode yang terstruktur dengan baik membuat hidup lebih mudah bagi pengembang. Tidak ada yang menghargai kode bebas bug yang ditulis dengan baik lebih dari pengembang.
Xamarin dengan sendirinya menyediakan mekanisme yang membuat penulisan kode lintas platform yang dapat digunakan kembali menjadi lebih mudah.
Pengembang seluler terbiasa dengan skenario di mana mereka harus menulis logika yang sama dua kali atau lebih untuk mendukung iOS, Android, dan platform lainnya. Tetapi dengan Xamarin, seperti yang dijelaskan pada bab sebelumnya, mudah untuk menggunakan kembali kode yang ditulis untuk satu platform untuk beberapa platform lain juga.
Di mana MvvmCross muncul?
MvvmCross, seperti namanya mungkin telah mengisyaratkan, memungkinkan untuk menggunakan pola MVVM dalam aplikasi Xamarin. Muncul dengan banyak perpustakaan, API, dan utilitas yang sangat berguna dalam pengembangan aplikasi lintas platform.
MvvmCross dapat secara signifikan mengurangi jumlah kode boilerplate yang akan Anda tulis (terkadang beberapa kali dalam bahasa yang berbeda) dalam pendekatan lain untuk pengembangan aplikasi.
Struktur Solusi MvvmCross
Komunitas MvvmCross merekomendasikan cara yang cukup sederhana dan efisien untuk menyusun solusi MvvmCross:
<ProjectName>.Core <ProjectName>.UI.Droid <ProjectName>.UI.iOS
Proyek Inti dalam solusi MvvmCross terkait dengan kode yang dapat digunakan kembali. Proyek Inti adalah proyek Xamarin PCL yang fokus utamanya adalah dapat digunakan kembali.
Kode apa pun yang ditulis dalam Core harus agnostik platform semaksimal mungkin. Seharusnya hanya berisi logika yang dapat digunakan kembali di semua platform. Proyek Inti tidak boleh menggunakan API Android atau iOS apa pun atau mengakses apa pun yang spesifik untuk platform apa pun.
Lapisan logika bisnis, lapisan data, dan komunikasi back-end adalah kandidat sempurna untuk disertakan dalam proyek Inti. Navigasi melalui hierarki tampilan (aktivitas, fragmen, dll.) akan dicapai di Core.
Sebelum melanjutkan, perlu dipahami satu pola desain arsitektur yang penting untuk memahami MvvmCross dan cara kerjanya. Seperti yang terlihat dari namanya, MvvmCross sangat bergantung pada pola MVVM.
MVVM adalah pola desain arsitektur yang memfasilitasi pemisahan antarmuka pengguna grafis dari logika bisnis dan data back-end.
Bagaimana pola ini digunakan di MvvmCross?
Nah, karena kami ingin mencapai reusability tinggi dari kode kami, kami ingin memiliki sebanyak yang kami bisa di Core kami, yang merupakan proyek PCL. Karena tampilan adalah satu-satunya bagian dari kode yang berbeda dari satu platform ke platform lainnya, kami tidak dapat menggunakannya kembali di seluruh platform. Bagian itu diimplementasikan dalam proyek-proyek yang terkait dengan platform.
MvvmCross memberi kita kemampuan untuk mengatur navigasi aplikasi dari Core menggunakan ViewModels.
Dengan dasar-dasar dan detail teknis, mari kita mulai dengan Xamarin dengan membuat proyek Inti MvvmCross kita sendiri:
Membuat Proyek Inti MvvmCross
Buka Xamarin Studio dan buat solusi bernama ToptalExampleSolution
:
Karena kita sedang membuat proyek Inti, adalah ide yang baik untuk tetap menggunakan konvensi penamaan. Pastikan akhiran Core
ditambahkan ke nama proyek.
Untuk mendapatkan dukungan MvvmCross, diperlukan untuk menambahkan perpustakaan MvvmCross ke proyek kami. Untuk menambahkan bahwa kita dapat menggunakan dukungan bawaan untuk NuGet di Xamarin Studio.
Untuk menambahkan perpustakaan klik kanan pada folder Packages dan pilih opsi Add Packages… .
Di kolom pencarian, kita dapat mencari MvvmCross, yang akan menyaring hasil yang terkait dengan MvvmCross seperti yang ditunjukkan di bawah ini:
Mengklik tombol Tambah Paket akan menambahkannya ke proyek.
Dengan MvvmCross ditambahkan ke proyek kami, kami siap untuk menulis kode Inti kami.
Mari kita definisikan ViewModel pertama kita. Untuk membuatnya, buat hierarki folder sebagai berikut:
Inilah yang dimaksud dengan masing-masing folder:
- Model: Model domain yang mewakili konten keadaan nyata
- Layanan: Folder yang menyimpan layanan kami (logika bisnis, basis data, dll.)
- ViewModel: Cara kami berkomunikasi dengan model kami
ViewModel pertama kami disebut FirstViewModel.cs
public class FirstViewModel : MvxViewModel { private string _firstName; private string _lastName; private string _fullName; public string FirstName { get { return _firstName; } set { _lastName = value; RaisePropertyChanged(); } } public string LastName { get { return _lastName; } set { _lastName = value; RaisePropertyChanged(); } } public string FullName { get { return _fullName; } set { _fullName = value; RaisePropertyChanged(); } } public IMvxCommand ConcatNameCommand { get { return new MvxCommand(() => { FullName = $"{FirstName} {LastName}"; }); } public IMvxCommand NavigateToSecondViewModelCommand { get { return new MvxCommand(() => { ShowViewModel<SecondViewModel>(); }); } } }
Sekarang setelah kita memiliki ViewModel pertama, kita dapat membuat tampilan pertama dan mengikat semuanya bersama-sama.
Android UI
Untuk menampilkan konten ViewModel, kita perlu membuat UI.
Langkah pertama untuk membuat UI Android adalah membuat proyek Android dalam solusi saat ini. Untuk melakukannya, klik kanan pada nama solusi dan pilih Add -> Add New Project… . Di wizard, pilih aplikasi Android dan pastikan Anda memberi nama proyek Anda ToptalExample.UI.Droid
.
Seperti yang dijelaskan sebelumnya, sekarang kita perlu menambahkan dependensi MvvmCross untuk Android. Untuk melakukannya, ikuti langkah yang sama seperti untuk proyek Core untuk menambahkan dependensi NuGet.
Setelah menambahkan dependensi MvvmCross, diperlukan untuk menambahkan referensi ke proyek Inti kami sehingga kami dapat menggunakan kode kami yang tertulis di sana. Untuk menambahkan referensi ke proyek PCL, klik kanan pada folder Referensi dan pilih opsi Edit Referensi… . Pada tab Proyek, pilih proyek Inti yang dibuat sebelumnya dan klik OK.

Bagian selanjutnya bisa sedikit rumit untuk dipahami.
Sekarang kita harus memberitahu MvvmCross bagaimana seharusnya mengatur aplikasi kita. Untuk melakukan itu, kita harus membuat kelas Setup
:
namespace ToptalExample.UI.Droid { public class Setup : MvxAndroidSetup { public Setup(Context context) : base(context) { } protected override IMvxApplication CreateApp() { return new Core.App(); } } }
Seperti yang dapat dilihat dari kelas, kami memberi tahu MvvmCross ke CreateApp
berdasarkan implementasi Core.App
, yang merupakan kelas yang ditentukan dalam Core dan ditunjukkan di bawah ini:
public class App : MvxApplication { public override void Initialize() { RegisterAppStart(new AppStart()); } } public class AppStart : MvxNavigatingObject, IMvxAppStart { public void Start(object hint = null) { ShowViewModel<FirstViewModel>(); } }
Di kelas App
, kami membuat instance AppStart
, yang akan menampilkan ViewModel pertama kami.
Satu-satunya yang tersisa sekarang adalah membuat file Tata Letak Android yang akan diikat oleh MvvmCross:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:andro xmlns:local="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <EditText android:layout_width="match_parent" android:layout_height="match_parent" local:MvxBind="Text FirstName" /> <EditText android:layout_width="match_parent" android:layout_height="match_parent" local:MvxBind="Text LastName" /> <TextView android:layout_width="match_parent" android:layout_height="match_parent" local:MvxBind="Text FullName" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" local:MvxBind="Click ConcatNameCommand" /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" local:MvxBind="Click NavigateToSecondViewModelCommand" /> </LinearLayout>
Dalam file layout, kami memiliki binding yang secara otomatis diselesaikan oleh MvvmCross. Untuk EditText
, kami membuat pengikatan untuk properti Teks, yang akan menjadi pengikatan dua arah. Setiap perubahan yang dipanggil dari sisi ViewModel akan secara otomatis tercermin pada tampilan dan sebaliknya.
Kelas View
dapat berupa aktivitas atau fragmen. Untuk kesederhanaan, kami menggunakan aktivitas yang memuat tata letak yang diberikan:
[Activity(Label = "ToptalExample.UI.Droid", Theme = "@style/Theme.AppCompat", MainLauncher = true, Icon = "@mipmap/icon")] public class MainActivity : MvxAppCompatActivity<FirstViewModel> { protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); SetContentView(Resource.Layout.Main); } }
Untuk tombol pertama, kami memiliki pengikatan perintah yang berarti ketika kami mengklik tombol MvvmCross akan memanggil ContactNameCommand
dari ViewModel.
Untuk tombol kedua, kita akan menampilkan ViewModel lain.
UI iOS
Membuat proyek iOS tidak jauh berbeda dengan membuat proyek Android. Anda harus mengikuti langkah serupa untuk menambahkan proyek baru, hanya saja kali ini, alih-alih Android, buat saja proyek iOS. Pastikan Anda menjaga konvensi penamaan tetap konsisten.
Setelah menambahkan proyek iOS, Anda perlu menambahkan dependensi untuk MvvmCross iOS. Langkah-langkahnya benar-benar sama seperti untuk Core dan Android (klik kanan pada Referensi di proyek iOS Anda dan klik Tambahkan Referensi… ).
Sekarang, seperti yang kita lakukan untuk Android, diperlukan untuk membuat kelas Setup
, yang akan memberi tahu MvvmCross cara mengatur aplikasi kita.
public class Setup : MvxIosSetup { public Setup(MvxApplicationDelegate appDelegate, IMvxIosViewPresenter presenter) : base(appDelegate, presenter) { } protected override MvvmCross.Core.ViewModels.IMvxApplication CreateApp() { return new App(); } }
Perhatikan bahwa kelas Setup
sekarang memperluas MvxIosSetup dan, untuk Android, itu memperluas MvxAndroidSetup .
Satu tambahan di sini adalah kita harus mengubah kelas AppDelegate
kita.
AppDelegate
di iOS bertanggung jawab untuk meluncurkan antarmuka pengguna, jadi kami harus memberi tahu bagaimana tampilan akan disajikan di iOS. Anda dapat mempelajari lebih lanjut tentang presenter di sini.
[Register("AppDelegate")] public class AppDelegate : MvxApplicationDelegate { // class-level declarations public override UIWindow Window { get; set; } public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions) { Window = new UIWindow(UIScreen.MainScreen.Bounds); var presenter = new MvxIosViewPresenter(this, Window); var setup = new Setup(this, presenter); setup.Initialize(); var startup = Mvx.Resolve<IMvxAppStart>(); startup.Start(); Window.MakeKeyAndVisible(); return true; } }
Untuk menampilkan VIewModel kita, kita perlu membuat view. Untuk itu, mari buat ViewController dengan mengklik kanan pada proyek dan memilih Add -> New File dan pilih ViewController dari bagian iOS, yang akan kita beri nama FirstViewController.
Xamarin membuat tiga file di mana kita akan menentukan apa yang akan menjadi binding kita. Tidak seperti Android, untuk iOS, kita harus mendefinisikan binding kita dengan cara yang berbeda, melalui kode (walaupun kita dapat melakukannya di Android juga dan, untuk beberapa kasus, itu diperlukan).
Ketika diperlukan untuk menavigasi antar tampilan, itu dilakukan melalui ViewModel. Dalam perintah NavigateToSecondViewModelCommand
, metode ShowViewModel<SecondViewModel>()
akan menemukan tampilan yang sesuai dan menavigasi ke sana.
Namun, bagaimana MVVMCross mengetahui tampilan mana yang akan dimuat?
Tidak ada sihir di dalamnya. Saat kami membuat tampilan untuk Android (Aktivitas atau Fragmen), kami memperluas salah satu kelas dasar dengan parameter tipe ( MvxAppCompatActivity<VM>
). Saat kita memanggil ShowViewMolel<VM>
, MvvmCross mencari View
yang memperluas kelas Activity
atau Fragment
dengan parameter tipe VM
. Inilah sebabnya mengapa Anda tidak diizinkan memiliki dua kelas tampilan untuk ViewModel yang sama.
Pembalikan Kontrol
Karena Xamarin hanya menyediakan pembungkus C# di sekitar API asli, Xamarin tidak menyediakan segala bentuk injeksi ketergantungan (DI) atau mekanisme inversi kontrol (IoC).
Tanpa injeksi dependensi runtime atau injeksi waktu kompilasi, tidak mudah untuk membuat komponen yang digabungkan secara longgar, dapat digunakan kembali, dapat diuji, dan mudah dirawat. Ide IoC dan DI telah dikenal sejak lama; detail tentang IoC dapat ditemukan di banyak artikel online. Anda dapat mempelajari lebih lanjut tentang pola-pola ini dari artikel pengantar Martin Fowler.
IoC telah tersedia sejak versi awal MvvmCrosses, dan memungkinkan injeksi dependensi saat runtime saat aplikasi dimulai dan kapan pun diperlukan.
Untuk mendapatkan komponen yang digabungkan secara longgar, kita seharusnya tidak pernah membutuhkan implementasi kelas yang konkret. Membutuhkan implementasi konkret membatasi kemampuan untuk mengubah perilaku implementasi selama runtime (Anda tidak dapat menggantinya dengan implementasi lain). Itu membuat sulit untuk menguji komponen ini.
Untuk alasan itu, kami akan mendeklarasikan antarmuka yang akan kami implementasikan secara konkret.
public interface IPasswordGeneratorService { string Generate(int length); }
Dan implementasi:
public class PasswordGeneratorService : IPasswordGeneratorService { public string Generate(int length) { var val; var res = new StringBuilder(); var rnd = new Random(); while (0 < length--) { res.Append(valid[rnd.Next(valid.Length)]); } return res.ToString(); } }
ViewModel kami sekarang dapat meminta turunan dari antarmuka IPasswordGenerationService
, yang kami bertanggung jawab untuk menyediakannya.
Agar MvvmCross menginjeksi implementasi PasswordGeneratorService
saat runtime, kita perlu memberi tahu MvvmCross implementasi mana yang akan digunakan. Jika kita ingin menggunakan satu implementasi untuk kedua platform, kita dapat mendaftarkan implementasi di App.cs
, setelah pendaftaran aplikasi:
public override void Initialize() { RegisterAppStart(new AppStart()); Mvx.LazyConstructAndRegisterSingleton<IPasswordGeneratorService, PasswordGeneratorService>(); }
Panggilan di atas ke metode statis LazyConstructAndRegisterSingleton<TInterface, TType>
mendaftarkan implementasi yang akan disuntikkan. Metode ini mendaftarkan implementasi yang sesuai tetapi tidak membuat objek.
Objek dibuat hanya jika diperlukan dan hanya sekali karena terdaftar sebagai singleton.
Jika kita ingin segera membuat objek tunggal, itu dapat dicapai dengan memanggil Mvx.RegisterSingleton<TInterface>()
.
Ada kasus di mana kita tidak ingin hanya memiliki lajang dalam aplikasi kita. Objek kami mungkin tidak aman untuk thread atau mungkin ada alasan lain mengapa kami ingin selalu memiliki instance baru. Jika demikian, MvvmCross menyediakan metode Mvx.RegisterType<TInterface,TType>()
, yang dapat digunakan untuk mendaftarkan implementasi dengan cara membuat instance baru kapan pun diperlukan.
Jika Anda perlu menyediakan implementasi konkret terpisah untuk setiap platform, Anda selalu dapat melakukannya di proyek khusus platform:
public class DroidPasswodGeneratorService : IPasswordGeneratorService { public string Generate(int length) { return "DroidPasswordGenerator"; } }
Dan pendaftaran implementasi kami dilakukan di kelas Setup.cs
di bawah proyek Droid:
protected override void InitializePlatformServices() { base.InitializePlatformServices(); Mvx.LazyConstructAndRegisterSingleton<IPasswordGeneratorService, DroidPasswodGeneratorService>(); }
Setelah inisialisasi kode PCL, MvvmCross akan memanggil InitializePlatformServices
dan mendaftarkan implementasi layanan khusus platform kami.
Saat kami mendaftarkan beberapa implementasi tunggal, MvvmCross hanya akan menggunakan implementasi yang didaftarkan terakhir. Semua pendaftaran lainnya akan dibuang.
Bangun Aplikasi Lintas Platform dengan Xamarin
Dalam artikel ini, Anda telah melihat bagaimana Xamarin memungkinkan Anda untuk berbagi kode di berbagai platform dan tetap mempertahankan nuansa dan kinerja asli aplikasi.
MvvmCross memberikan lapisan abstraksi lain yang semakin meningkatkan pengalaman membangun aplikasi lintas platform dengan Xamarin. Pola MVVM menyediakan cara untuk membuat navigasi dan alur interaksi pengguna yang umum untuk semua platform, membuat jumlah kode khusus platform yang perlu Anda tulis terbatas pada tampilan saja.
Saya harap artikel ini memberi Anda alasan untuk mengintip Xamarin dan memotivasi Anda untuk membangun aplikasi lintas platform berikutnya dengannya.