کانال بله, جهت پشتیبانی و اطلاع رسانی کانال بله, جهت پشتیبانی و اطلاع رسانی
عضویت

|آموزش xamarin|زامارین برای Java developer ها|

دوره آموزش زامارین

آموزش Xamarin برای Java developer ها


اگر شما یک Java developer هستید، در این بخش میتوانید از توانایی های خود، کد های موجود در Xamarin platform و همچنین کد های موجود C# استفاده کنید و خواهید آموخت که سینتکس C# بسیار شبیه سینتکس Java میباشد و این دو زبان دارای قابلیت های مشابهی هستند. علاوه بر این، قابلیت های منحصر به فردی از C# را می آموزید که کار توسعه شما را بسیار ساده میکند.

نگاه کلی


این مقاله به معرفی برنامه نویسی باC# را برای Java developer میپردازد و در درجه اول بر قابلیت های C# که در توسعه اپلیکیشن های Xamarin.Forms به آن نیز دارید، متمرکز میشود. همچنین این مقاله، تفاوت این قابلیت ها با معادل آنها در Java را مشخص میکند و قابلیت هایی از C# ( مرتبط با Xamarin.Android ) که در جاوا وجود ندارند را نیز معرفی میکند. لینک هایی نیز برای مطالب بیشتر مرتبط با هر بخش ارائه شده است تا شما بتوانید از این مقاله برای مطالعات بیشتر در زمینه C# و .NET نیز استفاده کنید.

اگر شما با Java آشنا هستید، به زودی احساس آشنایی کامل با سینتکس C# خواهید کرد. سینتکس C# بسیار شبیه Java است به طور مثال C# هم مانند Java ، C و C++ یک زبان " curly brace " ای است. در زمینه های مختلفی سینتکس Java مانند زیر مجموعه ای از سینتکس C# میباشد.

تعداد زیادی از مشخصات Java در C# نیز یافت میشوند مانند:

  • برنامه نویسی شی گرا مبنی بر کلاس ها (class-based)
  • Strong typing
  • پشتیبانی رابط ها ( interfaces)
  • Generics
  • Garbage collection
  • کامپایل در زمان اجرا

هر دو زبان C# و Java در یک محیط کامپایل مدیریت شده به زبان میانی کامپایل میشوند، هر دو statically-typed هستند و هر دو زبان با نوع String به شکلی تغییر ناپذیر رفتار میکنند. هر دو زبان از کلاس های سلسله مراتبی از یک راس ( single-rooted) استفاده میکنند. مانند Java ، C# نیز فقط از single inheritance پشتیبانی میکند و متد های global را مجاز نمیداند. در هر دو زبان اشیا بر روی پشته با کلیدواژه new ایجاد میشوند و اشیا زمانی که مورد استفاده قرار نگیرند garbage-collected میشوند. هر دو زبان سمنتیک try/catch را به عنوان یک exception handling معرفی میکنند و هر دو از tread management و همگام سازی پشتیبانی میکنند.

با این حال تفاوت های زیادی نیز بین Java و C# وجود دارد؛ به عنوان مثال :

  • Java ( مانند استفاده در Android) اجازه استفاده از متغیر های محلی با نوع ضمنی را نمیدهد( implicitly- typed) اما C# از کلیدواژه var پشتیبانی میکند.
  • در جاوا تنها pass by value برای پارامتر ها مجازاست اما در C# میتوان از pass by reference نیز استفاده کرد( C# کلیدواژه های ref و out را برای pass by reference معرفی میکند که معادلی برای آن در جاوا وجود ندارد.)
  • جاوا از preprocessor directive (پیش پردازنده ها) مانند #define پشتیبانی نمیکند.
  • جاوا از نوع بدون علامت integer ( unsigned integer ) ها پشتیبانی نمیکند اما C# دسترسی به نوع هایی مانند uLong، uint، ushort و byte را فراهم میکند.
  • جاوا از operator overloading پشتیبانی نمیکند اما در C# شما میتوانید از operator and conversions overload استفاده کنید.
  • در جاوا، کد switch statement میتواند پس از هر switch به switch بعدی برود اما در C# هر switch statement باید با break statement پایان یابد.
  • در جاوا میتوان استثنا را با متدی با کلیدواژه throws مشخص کرد که در C# پشتیبانی نمیشود.
  • C# از Language-Integrated Query (LINQ) پشتیبانی میکند که به شما اجازه میدهد از کلمات رزرو شده from ، select و where برای نوشتن query برای مجموعه ها( چیزی شبیه به query های دیتابیس) استفاده کنید.

البته تفاوت های بین C# و جاوا بیشتر از آن است که ما بتوانیم همه را در این مقاله بگنجانیم و همچنین هر دو این زبان ها همچنان در حال رشد هستند و تفاوت های آنها نیز در طول زمان تغییر میکند؛ مثلا در Java 8 که هنوز در Android toolchain نیست، عبارات lambda (λ) به سبک C# پشتیبانی میشوند. مهمترین تفاوت هایی که Java developer ها در Xamarin.Android با آن مواجه میشوند به شرح زیر است:

  • Going from Java to C# Development که تفاوت های پایه ای C# و جاوا را معرفی میکند.
  • Object-Oriented Programming Features که مهمترین تفاوت ها در قابلیت های شی گرا را در این دو زبان معرفی میکند.
  • Keyword Differences که جدولی از کلیدواژه های کاربردی معادل در C# است که لینک توضیحات آن نیز موجود است.

C# قابلیت های کلیدی زیادی را برای Xamarin.Android فراهم کرده است که در حال حاضر برای Java developer ها در Android قابل دسترسی نیست. این قابلیت ها به شما کمک میکنند در زمان کمتر، کد بهتری بنویسید:

  • Properties - در C# properties system شما میتوانید به member variable ها به راحتی و مستقیم، (بدون نیاز به استفاده از متد های setter و getter ) دسترسی پیدا کنید.
  • Lambda Expressions - در C# شما میتوانید از متد های بی نام (anonymous) که متد های lambda(λ) نیز گفته میشوند استفاده کنید تا متد هایی با کارایی بالا و به صرفه بنویسید. برای جلوگیری از نوشته اشیایی که فط یک بار استفاده میشوند، شما میوانید local state را، بدون نیاز به اضافه کردن پارامتر، به یک متد اضافه کنید.
  • Event Handling - C# از پشتیبانی در سطح زبان برای برنامه نویسی Event-driven پشتیبانی میکند. یک شی میتواند درخواست کند که در صورت رخ دادن یک اتفاق دلخواه، باخبر شود. کلیدواژه event یک مکانیزم انتشار چندکاره را تعریف میکند که کلاس منتشر کننده میتواند از آن برای باخبر کردن اشیا event subscriber استفاده کند.

در نهایت، جاوا به شما اجازه میدهد از leverage existing Java assets با تکنولوژ که به Binding شناخته میشود، استفاده کنید. شما همچنین میتوانید از کد های موجود جاوا، فرم وورک ها و کتابخانه های C# ، با کمک binding generator های اتوماتیک Xamarin ، استفاده کنید. برای این کار شما به سادگی باید یک کتابخانه static در جاوا تولید کنید و آن را با کمک binding در C# نمایش دهید.

توجه !

برنامه نویسی اندروید از ورژن مشخصی از زبان جاوا استفاده میکند که تمامی قابلیت های Java 7 و زیر مجموعه ای از Java 8 را پشتیبانی میکند.

برخی از قابلیت های گفته شده در این صفحه ( مانند کلیدواژه var در C#) در ورژن های جدید تر جاوا وجود دارند (مانند var در Java10) اما برای توسعه دهندگان اندروید قابل استفاده نیستند.

تبدیل شدن به C# developer برای Java developer ها در زامارین


بخش های زیر، تفاوت های پایه ای C# و جاوا را نشان میدهد. در بخش های بعدی تفاوت های شی گرایی بین این دو زبان بحث میشود.

Libraries vs. assemblies


جاوا معمولا کلاس های مربوط به خود را در فایل ها .jar بسته بندی میکند. در C# و .NET بیت های قابل استفاده دوباره از کد های کامپایل شده در assemblies بسته بندی میشوند که معمولا در فایل های .dll قرار میگیرند. یک assembly، یک واحد توسعه برای کد های C#/.NET میباشد و معمولا هر assembly با یک پروژه C# مرتبط است. Assembly ها شمال کد های میانی هستند( Intermediate code) که در زمان اجرا در همان لحظه کامپایل میشوند.

Packages vs. namespace


C# از کلیدواژه namespace برای گروه بندی type های مرتبط استفاده میکند که مفهومی شبیه به کلیدواژه package در جاوا دارد. به طور معمول اپلیکیشن های Xamarin.Android در یک namespace که برا اپ ایجاد شده، قرار میگیرند؛ برای مثال، کد C# زیر یک WeatherApp namespace برای اپلیکیشن گزارش هوا تعریف میکند:

    namespace WeatherApp
    {
        ...

Importing type


زمانی که از type های تعریف شده در namespace های خارجی استفاده میکنید، این type ها را با عبارت using ، بارگیری (import) میکنید ( که مفهومی بسیار شبیه به عبارت import در جاوا دارد). در جاوا شما میتوانید یک type را با عبارتی شبیه زیر بارگیری کنید:

    import javax.swing.JButton

و همچنین میتوانید تمام یک پکیج جاوا را با عبارتی به شکل زیر بارگیری کنید:

    import javax.swing.*

عبارت using در C# نیز کارکردی بسیار مشبه دارد، اما به شما اجازه میدهد تا تمام پکیج را بدون قرار دادن wildcard بارگیری کنید؛ برای مثال، اغلب در ابتدای فایل های Xamarin.Android عباراتی که با استفاده از using نوشته شده، مانند مثال زیر، وجود دارد:

    using System;
    using Android.App;
    using Android.Content;
    using Android.Runtime;
    using Android.Views;
    using Android.Widget;
    using Android.OS;
    using System.Net;
    using System.IO;
    using System.Json;
    using System.Threading.Tasks;

این عبارات عمکلردهایی را از namespace های System، Android.App، Android.Contentent و... بارگیری میکند.

Generics


جاوا و C# هر دو از generic ها پشتیبانی میکنند، که یک placeholder است که به شما اجازج میدهد type های مختلفی را در زمان کامپایل ایجاد کنید. با این حال، generic ها در C# اندکی متفاوت اند. در جاوا type erasure تنها در زمان کاپایل، نه زمان اجرا، اطلاعات type را دراختیار ما میگذارد. اما .NET common language runtime (CLR) ، از generic type ها پشتیبانی کامل میکند، بدین معنی که C# در زمان اجرا به اطلاعات type دسترسی دارد. در کاربرد های معمول توسعه با Xamarin.Android ، اهمیت این تفاوت چندان مشخص نیست، اما اگر از reflection استفاده کنید، به دسترسی به اطلاعات type در زمان اجرا به شدت نیاز خواهید داشت.

در Xamarin.Android ، اغلب متد generic، FindByView را، که برای گرفتن رفرنس از یک layout control استفاده میشود، را مشاهده میکنید. این متد یک پارامتر generic type میپذیرد که نوع control ای را که باید بیابد، مشخص میکند؛ برای مثال:

    TextView label = FindViewById (Resource.Id.Label);

در این مثال، FindByView یک رفرنس به control TextView ، که به عنوان label تعریف شده، را میگیرد و سپس آن را نوع TextView بازمیگرداند.

برای اطلاعات بیشطر درباره generic ها، Generics را ببینید. توجه کنید Xamarin.Android از کلاس های محدود generic C# پشتیبانی میکند؛ برای اطلاعات بیشتر Limitations را ببینید.

قابلیت های برنامه نویسی شی گرا


زبانهای جاوا و C# دارای اصصلاحات شی گرایی مشابهی هستند:

  • تمامی کلاس های باید از یک شی single root مشتق شوند.( تمام اشیا جاوا از java.lang.Object و اشیا C# از System.Object مشتق میشوند.
  • Instance های کلاس ها از نوع reference هستند.
  • زمانی که میخواهید به properties و متد های یک instance دسترسی پیدا کنید باید از عملگر “.” استفاده کنید.
  • هر دو زبان دارای garbage collection هستند، در نتیجه نمیتوان اشیا استفاده نشده را آزاد کرد( مانند C++ کلیدواژه delete وجود ندارد.)
  • کلاس ها را میتوان به شکل سلسله مراتبی گسترش داد و هر دو زبان تنها کلاس های single base را در هر type مجاز میدانند.
  • شما میتوانید رابط ( interface) تعریف کنید که در کلاس ها منتقل شوند( inherited).

اما تفاوت هایی نیز وجود دارد:

  • جاوا دارای دو قابلیت مهم است که C# از آنها پشتیبانی نمیکند: کلاس های بی نام ( anonymous) و کلاس های داخلی. ( C# از تعریف کلاس های تو در تو پشتیبانی نمیکند و کلاس های تو در تو در C# مانند کلاس های تو در تو static در جاوا هستند.)
  • C# از C-style type (struct) پشتیبانی میکند ولی جاوا از آنها پشتیبانی نمیکند.
  • در C# شما میتوانید با استفاده از کلیدواژه partial تعریف کلاس را در یک سورس فایل جداگانه پیاده سازی کنید.
  • در رابط های C# نمیتوان filed تعریف کرد.
  • C# از سینتکس C++ destructor برای نشان دادن finalizer ها استفاده میکند که با سینتکس متد finalize در جاوا متفاوت است، اما سمنتیک مشابهی دارد. ( توجه کنید که در C#، destructor ها به شکل اتوماتیک base-class destructor را صدا میزند اما در جاوا super.finalize صدا زده میشود.)

Class inheritance


برای گسترش یک کلاس در جاوا، میتوانید از کلیدواژه extends استفاده کنید. برای نشان دادن اشتقاق در C# از ":" استفاده میشود؛ برای مثال، در اپلیکیشن های Xamarin.Android اغلب اشتقاق از یک کلاس را به شکل کد زیر مشاهده میکنید:

    public class MainActivity : Activity
    {
        ...

در این مثال، MainActivity از کلاس Activity مشتق شده است.

برای تعریف پشیبانی از رابط در جاوا، میتوانید از کلیدواژه implements استفاده کنید که در C# این کار با اضافه کردن نام رابط به لیست کلاس هایی که اشتقاق از آنها صورت گرفته انجام میشود که در کد زیر نشان داده شده است:

    public class SensorsActivity : Activity, ISensorEventListener
    {
        ...
    

در این مثال SensorsActivity از Activity مشتق شده است و عملکرد هایی که در رابط ISensorEventListener تعریف شده را پیاده سازی میکند. توجه کنید که لیست رابط ها باید پس از لیست base-class ها بیاید( در غیراین صورت compile time error دریافت میکنیم). طبق قرارداد در C# نام رابط ها با حرف بزرگ “I” آغاز میشود تا بتوان کلاس ها و رابط ها را بدون نیاز به کلیدواژه implements شناسایی کنیم.

اگر بخواهیم از subclass شدن یک کلاس در C# جلوگیری کنیم نام آن را با sealed و در جاوا نام آن را با final آغاز میکنیم(کلاس دیگری نمیتواند از این کلاس مشتق شود).

Properties


در جاوا متد های mutator (setters) و متد های inspector ( getters) اغلب برای کنترل تغییرات کلاس ها و اعضا آنها و همچنین پنهان کردن و حفاظت آنها ازکد های خارجی، استفاده میشوند؛ برای مثال، کلاس TextViewدر اندروید، متد های getText و setText را در اختیار ما قرار میدهد. C# از مکانیزمی مشابه اما مستقیم تر به نام properties استفاده میکند. کاربران کلاس های C# میتوانند به property ها مانند filed ها دسترسی پیدا کنند اما هر دسترسی با یک بار صدا زدن متد همراه است. این متد های پنهان میتوانند عوارض جانبی مانند قرار دادن متفاوت، انجام تبدیل و یا تغییر حالت( state) شی ایجاد کند.

Property هااغلب برای دسترسی و تغییر UI (User Interface) اشیا نیز استفاده میشوند؛ برای مثال:

    int width = rulerView.MeasuredWidth;
    int height = rulerView.MeasuredHeight;
    ...
    rulerView.DrawingCacheEnabled = true;

در این مثال، مقادیر طول و عرض شی rulerView، با دسترسی به property های MeasuredHeight و MeasuredWidth آن، خوانده میشوند. زمانی که property ها خوانده میشوند، مقادیرآنها از فیلد های مرتبط (اما پنهان) گرفته میشود( در پشت صحنه) و به صدا کننده داده میشود. شی rulerView ممکن است مقادیر طول و عرض را برحسب یک واحد مشخص( مثلا pixels) ذخیره کرده باشد و زمانی که دسترسی به آنها صورت میگیرد، آنها را در حال انتقال، به واحد دیگری ( مثالاmillimeters ) تبدیل کند.

شی rulerView همچنین دارای یک property به نام DrawingCacheEnabled است که در مثال کد بالا مقدار آن true قرار داده شده است. پشت صحنه، یک فیلد مرتبط با مقدار جدید آپدیدت میشود و حتی ممکن است تغییراتی در جنبه های دیگر state شی rulerView ایجاد شود؛ برای مثال، زمانی که مقدار DrawingCacheEnabled ، false قرار داده شود، rulerView ممکن است هر اطلاعاتی مربوط به آن را که در شی ذخیره شده، حذف کند.

دسترسی به اشیا میتواند read/write، read-only و یا write-only باشد و همچنین شما میتوانید از access modifier های مختلفی برای نوشته و خوانده استفاده کنید؛ مثلا یک property میتواند طبق تعریف دسترسی public read و private write داشطه باشد.

Calling base class methods


برای صدا کردن یک base-class constructor در C#، میتوانید از ":" و کلیدواژه base استفاده کنید و سپس initializer list را قرار دهید. این base constructor بلافاصله پس ازلیست پارامتر های constructor مشتق شده، صدا زده میشود. کامپایلر Base-class constructor را در شروع derived constructor، شروع بدنه ی متد، صدا میزند. قطعه کد زیر نشان میدهد که چگونه در یک اپلیکیشن Xamarin.Android، base constructor از طریق derived constructor صدا زده میشود:

    public class PictureLayout : ViewGroup
    {
        ...
        public PictureLayout (Context context)
               : base (context)
        {
            ...
        }
        ...
    }

در این مثال، کلاس PictureLayout از کلاس ViewGroup مشتق شده است. pictureLayout Constructor نشان داده شده در مثال بالا یک آرگومان Context میپذیرد و آن را، با صدا زدن base(context)، به ViewGroup constructor پاس میدهد.

برات صدازدن یک متد base-class در C#، از کلید واژه base استفاده میکنیم؛ برای مثال در اپلیکیشن های Xamarin.Android ، اغلب به شکل زیر متد های base را صدا میکنیم :

    public class MainActivity : Activity
    {
        ...
        protected override void OnCreate (Bundle bundle)
        {
            base.OnCreate (bundle);

در این مورد، متد OnCreate تعریف شده در کلاس مشتق شده(MainActivity) متد OnCreate کلاس base را (Activity) صدا میکند.

Access modifiers


جاوا و C# از Access modifier های public، private و protected پشتیبانی میکنند، اما C# از دو access modifier دیگر نیز پشتیبانی میکند:

  • internal- اعضا کلاس تنها در همان assembly در دسترس اند.
  • protected- اعضا کلاس در assembly تعریف کنند، کلاس تعریف کننده و کلاس های مشتق شده آن، در داخل و خارج assembly ، در دسترس اند.

Virtual and override methods


جاوا و C# ازpolymorphism، که قابلیت برخورد با اشیا مرتبط به شکلی مشابه است، پشتیبانی میکنند. در هر دو زبان، میتوانید از یک رفرنس base-class برای ارجاع به یک شی derived-class استفاده کنید و متد های کلاس مشتق شده میتوانند متد های کلاسهای base خود را override کنند. هر دو زبان دارای مفهومvirtual method ، یک متد که در کلاس base طراحی شده است تا یک متد در کلاس مشتق شده جای آن را بگیرد، است. مانند جاوا، C# نیز از کلاس ها و متد های abstract پشتیبانی میکند.

اما تفاوت هایی در نحوه تعریف و override متدهای virtual در جاوا و C# وجود دارد:

  • در C# متد ها به شکل پیش فرض non-virtual هستند. کلاس های parent باید با کلیدواژه virtual مشخص کنند کدام متد ها میتوانند override شوند. اما در جاوا تمام متد ها به صورت پیش فرض virtual هستند.
  • برای جلوگیری از override شدن یک متد در C# میتوانید به راحتی کلیدواژه virtual را در مقابل آن قرار ندهید، اما در جاوا باید کلیدواژه final استفاده کنید تا مشخص شود که یک متد نمیتواند override شود.
  • کلاس های مشتق شده C# باید کلیدواژه override استفاده کنند تا override شدن یک متد base-class را نشان دهند.

Lambda expressions


C# این امکان ایجاد closure: ، که متد های بی نامی است که میتوانند متد را در حالت خاتمه قرار دهند، را در یک خط به ما میدهد. با استفاده از عبارات لاندا میتوانید، با حجم کمتری کد نسبت به جاوا، عملکرد دلخواه خود را پیاده سازی کنید.

عبارات لاندا به شما اجازه میدهند ازتشریفات اضافی ایجاد کلاس های یکبار مصرف و یا کلاس های بی نام ، مانند جاوا، بگذرید و تنها منطق کد خود را بنویسید. همچنین عبارات لاندا به متغییر های متد های اطراف خود دسترسی دارند و نیازی به نوشتن پاترامتر های طولانی و پاس دادن آنها به متد های خود ندارید.

در C# ، عبارات لاندا با عملگر => ایجاد میشوند که در مثال زیر نشان داده شده است:

    (arg1, arg2, ...) => {
        // implementation code
    };

در Xamarin.Android، عبارات لاندا برای تعریف event handler ها استفاده میشوند؛ برای مثال:

    button.Click += (sender, args) => {
        clickCount += 1;    // access variable in surrounding code
        button.Text = string.Format ("Clicked {0} times.", clickCount);
    };

در این مثال، کد عبارت لاندا ( کدی که درون {} قرار دارد) یک شمارنده کلیک را افزایش میدهد و متن داخل Button را آپدیت میکند تا شمارنده کلیک را نمایش دهد. این عبارت لاندا همراه شی button به عنوان event handler آن ثبت شده است تا با هر کلیک صدا زده شود.(event handler ها با جزئیات بیشتر در ادامه توضیح داده میشوند.) در این مثال ساده، پارامترهای sender و args برای کد عبارت لاندا استفاده نمیشوند، اما برای ثبت event در این متد ضروری اند. در واقع، کامپایلر C# عبارت لاندا را به عنوان یک متد بی نام میبیند که در زمان کلیک شدن Button صدا زده میشود.

Event handling


یک شی از طریق event، subscriber ها را ازیک رخداد، باخبر میکند. بر خلاف جاوا که subscriber ها یک رابط listener که شامل یک متد callback است را پیاده سازی میکنند، C# پشتیبانی در سطح زبان را برای event handling از طریق delegate ها را فراهم میکند. یک delegate مانند یک تابع نشانه گر شی گرا type-safe است که از رفرنس شی و نشانه های متد محفافظت میکند. اگر یک شی بخواهد از یک رخداد باخبر شود، یک delegate ایجاد میکند و آن را به delegate شی باخبر کنند، ارسال میکند. زمانی که رخداد اتفاق می افتد، شی خبر رسان، متد شی delegate شده را، فعال میکند که به اشیا subscribe شده خبر رخداد را میدهد. در واقع در C#، event handler ها متد هایی هستند که با delegates ها فعال میشوند.

در C#، رخداد ها multicast هستند، و این به این معنی است که بیش از یک listener میتواند از یک رخداد مطلع شود. این تفاوت، زمانی که جاوا و C# را از جنبه سینتکس ثبت رخداد، مقایسه کنید، مشخص میشود. در جاوا شما یک متد SetXXXListener را برای ثبت رخداد صدا میکنید، اما در C# میتوانید برای اطلاع از رخداد ها ازعملگر =+ استفاده کنید تا متد خودرا در لیست event listener ها، deligate کنید. در جاوا برای متوقف کردن خبر رسانی باید SetXXXListener را صدا کنید اما در C# میتوانید از =- استفاده کنید تا delegate خود را از لیست event listener ها حذف کنید.

در Xamarin.Android اغلب event ها برای با خبر کردن اشیا از ارتباط کاربر با UI، استفاده میشود. معمولا UI control دارای اعضایی است که با کلیدواژه event تعریف شده اند ، برای با خبر شدن از تغییرات این اشیا UI، کافی است delegate خود را به آنها متصل کنید.


برای subscribe به یک رخداد:

1. یک شی delegate بسازید و آن را به متدی که میخواهید پس از رخداد فعال شود، رجوع دهید.

2. از علمگر =+ استفاده کنید تا delegate خود را به رخدادی که میخواهید از آن با خبر شوید، اضافه کنید.


مثال زیر یک delegate تعریف میکند( با استفاده از کلیدواژه delegate) تا کلیک شدن یک دکمه را نشان دهد. این Button-clicked handler با یک activity جدید آغاز میشود:

    startActivityButton.Click += delegate {
        Intent intent = new Intent (this, typeof (MyActivity));
        StartActivity (intent);
    };

اما حال شما میتوانید از عبارت λ برای اضافه شدن به یک رخداد استفاده کنید و از بخش کلیدواژه delegate، عبور کنید؛ برای مثال:

    startActivityButton.Click += (sender, e) => {
        Intent intent = new Intent (this, typeof (MyActivity));
        StartActivity (intent);
    };

در این مثال، شی startActivityButton دارای یک رخداد است و منتظر یک delegate با متد با اثر خاص است: متدی که ارسال کننده و آرگومان های یک رخداد را بپذیرد و void برگرداند. با این حال، برای اینکه وارد مشکلات تعریف یک delegate با این مشخصات و یا متد آن نشویم، اثر این متد را با (sender, e) و استفاده از عبارت λ ، برای پیاده سازی بدنه ی event handler ، میسازیم. توجه کنید که باید این لیست پارامتر ها را تعریف کنیم اما از پارامتر های آن، کهsender و e هستند، استفاده نمیکنیم.

مهم است که به خاطر داشته باشید که میتوانید یک delegate را با عملگر( =-) unsubscribe کنید، اما unsubscribe کردن یک عبات لاندا ممکن نیست و اقدام به این کار ممکن است باعث از دست رفتن حافظه شود. از روش لاندا تنها زمانی استفاده کنید که اطمینان دارید handler شما از رخداد unsubscribe نخواهد شد.

معمولا، برای تعریف event handler ها در Xamarin.Android ، از عبارات لاندا استفاده میکنیم. این روش مختصر برای نوشتن event handler ها ممکن است در ابتدا مرموز به نظر برسد، اما میتواند به طور قابل توجهی زمان خواندن و نوشته کد را برای شما کاهش دهد. با آشنایی بیشتر با این روش، آن را در کد ها به راحتی تشخیص میدهید (که در Xamarin.Android نیز بسیار استفاده میشود) و میتوانید زمان بیشتری را به منطق کد خود اختصاص دهید و وقت خود را صرف درگیری های سینتکسی زبان نکنید.

Asynchronous programming


برنامه نویسی ناهمگام راهی برای بهبود پاسخگویی کلی اپلیکیشن است. قابلیت های برنامه نویسی ناهمگام باعث میشود زمانی که بخشی از اپلیکیشن با یک عملیات طولانی درگیر است، بخش های دیگر آن به درستی کار کند. دسترسی به وب، پردازش تصاویر و خواندن و نوشن در فایل ها تنها مثال هایی از عملگر هایی هستند که میتوانند، در صورت استفاده نکردن از برنامه نویسی ناهمگام، کارکرد اپلیکیشن را متوقف کنند.

C# ، با کلیدواژه های async و await، برنامه نویسی ناهمگام را در سطح زبان پشتیبانی میکند. این قابلیت های زبان به شما اجازه میدهد به راحتی کدی بنویسید که کار های طولانی را، بدون متوقف کردن thread اصلی برنامه، انجام دهد. به طؤر خلاصه استفاده از کلیدواژه async در متد نشان میدهد که کد آن متد باید به شکل ناهمگام اجرا شود و نباید thread صدا کننده را متوقف کند. و کلید واژه await را زمانی که میخواهید متدی که دارای کلیدوژه async است را صدا کنید، استفاده میکنید. کامپایلر نقطه ای را که با await مشخص شده به عنوان شروع کدی میبیند که باید در background thread انجام شود و کد پس از صدا کننده ادامه پیدا میکند. زمانی که نتایج بخش ناهمگام مشخص شود پاسخ به کد صدا کننده در نقطه ی await برگردانده میشود. طبق قرارداد، نام متد هایی که به شکل ناهمگام اجرا میشوند با Async خاتمه میابد.

در اپلیکیشن های Xamarin.Android ، async و await معمولا برای این استفاده میشوند که thread های UI را، زمانی که اپلیکیشن در background درحال اجراست) برای پاسخ به ورودی های کاربر آزاد کنند( مثلا فشردن دکمه cancel ) .

در مثال زیر، یک button clicked event handler یک عملیات ناهمگام دانلود یک عکس از وب را اغاز میکند:

    downloadButton.Click += downloadAsync;
    ...
    async void downloadAsync(object sender, System.EventArgs e)
    {
        webClient = new WebClient ();
        var url = new Uri ("http://photojournal.jpl.nasa.gov/jpeg/PIA15416.jpg");
        byte[] bytes = null;
    
        bytes = await webClient.DownloadDataTaskAsync(url);
    
        // display the downloaded image ...

در این مثال، زمانی که کاربر دکمه dowloadButton را بزند، downloadDataTaskAsync event handler یک شی WebClient و یک شی Uri برای گرفتن یک عکس از URL مشخص شده، ایجاد میکند. سپس، متد DownloadDataTaskAsync را از شی WebClient صدا میکند تا عکس را از URL مشخص شده بگیرد.

توجه کنید که نام متد DownloadAsync دارای پسوند Async است، به این معنی که این متد به صورت ناهمگام اجرا میشود و نتیجه را برمیگرداند. و همچنین توجه کنید که پیش از صدا کردن DowloadDataAsync پیشوند await قرار گرفته است. اپلیکیشن اجرای event handler را ، از نقطه ای که await قرار گرفته است، به background thread منتقل میکند، تا زمانی که DownloadDataTaskAsync پایان یابد و نتیجه را برگرداند. در این حین UI اپلیکیشن میتواند همچنان به کار خود ادامه دهد و به ورودی های کاربر پاسخ دهد و event hander های دیگری را برای کنترل های دیگری آغاز کند. زمای که عملیات DownloadDataTaskAsync به پایان رسید( که ممکن است چندین ثانیه طول بکشد)، اجرا برنامه به متغیر byte که پاسخ DownloadDataTaskAync در آن قرار میگیرد، برمیگردد و و اجرا بقیه کد event handler، عکس دانلود شده را در UI thread صدا کننده، نمایش میده.

Keyword differences


کلیدواژه های زیادی بین جاوا و C# مشترک اند. اما تعدادی از کلیدواژه های جاوا دارای معادل هایی با نام های متفاوت در C# دارند که در جدول زیر بررسی شده اند:

توضیحات
C#
Java
برای تعریف مقادیر Boolean با مقادیر true و false استفاده میشود.
bool
boolean
کلاس ها و رابط هایی که کلاس از آنها مشتق شده را نشان میدهد.
:
extends
کلاس ها و رابط هایی که کلاس از آنها مشتق شده را نشان میدهد.
:
implements
برای بارگیری type ها ازیک namespace و همچنین تعریف namespace استفاده میشود.
using
imports
از اشتاق کلاس جلوگیری میکند؛ از override شدن property ها در کلاس های مشتق شده جلوگیری میکند.
sealed
final
تطابق یک شی با type مشخص شده آن را ارزیابی میکند.
is
instanceof
یک متد که به شکل خارجی پیاده سازی شده است را تعریف میکند.
extern
native
یک scope برای اشیا مرتبط ایجاد میکند.
namespace
package
پارامترهای متدی را مشخص میکند که چند نوع آرگومان میگیرد.
params T
T…
برای دسترسی به اعضا کلاس parent از داخل کلاس های مشتق شده، استفاده میشود.
base
super
از کد را قفل کرده و باز میکند.critical section
lock
synchronized

همچنین، کلیدواژه هایی در C# موجودند که دارای معادلی در جاوا نیستند و میتوان از آنها در Xamarin.Android استفاده کرد( این جدول میتواند زمانی که در حال خواندن کدهای نمونه Xamarin.Android هستید، کمک زیادی به شما بکند):

توضیحات
C#
بین نوع های سازگار و یا نوع های nullable ، تبدیل انجام میدهد.
as
متد و یا عبارت لاندا ناهمگام را مشخص میکند.
async
اجرای یک متد را تا پایان انجام یک کار متوقف میکند.
await
یک type، که یک integer هشت بیتی بدون علامت میباشد.
byte
برای محصور کردن یک متد و یا یک متد بی نام استفاده میشود.
delegate
یک enumeration، که یک مجموعه از ثابت هام نام گذاری شده است، را تعریف میکند.
enum
یک event را، در کلاس منتشر کننده، تعریف میکند.
event
از جابه جایی یک متغیر جلوگیری میکند.
fixed
یک متد accessor تعریف میکند که مقدار را از یک property میگیرد.
get
به یک پارامتر اجازه میدهد یک نوع less drived را در یک generic interface بپذیرد.
in
یک نام مستعار برای Object type در فرم ورک های .NET
object
تعریف کننده ی پارامتر های modifier یا پامتر های generic type .
out
یک متد را به گونه ای تعریف میکند که پیاده سازی آن به فایل و یا بکش های مختلفی تقسیم شود.
partial
مشخص میکند که تنها در زمان تعریف و یا توسط constructor کلاس میتوان به این عضو کلاس مقدار دهی کرد.
readonly
باعث میشود یک آرگومان pass by reference شود.( به جای pass by value)
ref
یک متد accessor تعریف میکند که میتواند به یک property مقدار بدهد.
set
نام مستعاری برای String type در فرم ورک .NET
string
یک value type که یک گروه از متغییر های مرتبط را محصور میکند.
struct
type یک شی را مشخص میکند.
typeof
یک متغییرمحلی با نوع implicitly-typed ایجاد میکند.
var
به مقداری که کد کاربر میخواهد به یک property بدهد، ارجاع میدهد.
value
به متد اجازه میدهد که در یک کلاس مشتق شده override شود.
virtual

Interoperating with existing java code


اگر یک کد جاوا با عملکرد درست دارید که نمیخواهید آن را به C# تغییر دهید، میتوانید از کتابخانه های جاوا خود در اپلیکیشن های Xamarin.Android ، با کمک دو روش زیر، استفاده کنید:

  • ساخت کتابخانه های java binding – با استفاده از این روش، شما از ابزار Xamarin.Android برای ایجاد C# wrapper بر type های جاوا، استفاده میکنید، این wrapper ها binding نام دارند. و در نتیجه، اپلیکیشن Xamarin.Android شما میتواند از فایل های .jar از طریق این wrapper ها استفاده کند.
  • Java Native Interface - Java Native Interface (JNI) یک فرم وورک است که به اپلیکیشن های C# این امکان را میدهد که از طریق یک کد جاوا صدازده شوند و یا آن را صدا کنند.

خلاصه


در این مقاله به معرفی برنامه نویسی Xamarin.Android با C#، از دیدگاه توسعه دهندگان جاوا، پرداختیم. تشابه های C# و جاوا را بررسی کردیم و تفاوت های کاربردی آنها را توضیح دادیم. به معرفی assembly ها و namespace ها و چگونگی بارگیری type های خارجی پرداختیم و خلاصه ای از تفاوت های access modifier ها، generic ها، اشتقاق از کلاس ها، صداکردن متد های base-class، override کردن متد ها و event handling را بررسی کردیم. قابلیت های C# که در جاوا موجود نیستند مانند property ها، برنامه نویسی ناهمگام با async/await، عبارات لاندا، C# delegate ها و سیستم event handling را معرفی کردیم. و همچنین جدول های موجود، اهمیت تفاوت کلیدواژه ها در C# را به مانشان دادند و توضیح داده شد که چگونه از کتابخانه های موجود جاوا استفاده کنیم و لینک هایی نیز برای اطلاعات بیشتر و مطالعه عمیق تر قرار داده شد.

1399/02/04 1926 495
رمز عبور : tahlildadeh.com یا www.tahlildadeh.com
نظرات شما

نظرات خود را ثبت کنید...