آموزش برنامه نویسی اندروید قسمت شانزدهم

1396/7/19 --- 5360

با سلام. مقاری هستم و جلسه 16 آموزش اندروید رو شروع میکنیم. این جلسه و 1 یا 2 جلسه بعد میخوام یه بازگشتی داشته باشیم مثل روال همیشگی به مطالب قبلی و گره هایی که توش بودو باز کنیم.

ترجیح میدم که از بحث thread ها شروع کنیم. اگر به یاد داشته باشید برای ساخت صفحه splash نیاز داشتیم یک delay ایجاد کنیم. و وارد بحث thread ها شدیم. بحثی که توی اندروید خیلی خیلی مطرح هست. اما مثل همیشه پیش نیازهایی دارد از جاوا که مثل همیشه در حد اشاره نکات مهمش رو میگم  و در ادامه نکاتی از اندروید.

*دوره

برای اینکه کامل این مفهوم را متوجه بشید برمیگردیم به کلاس ها. با مفهوم کلاس باید خوب آشنا شده باشید. به یاد داشته باشید کلاس انسان را مثال زدیم. که میشد برای آن یک نمونه از انسان تعریف کرد. هر انسان یک سری ویژگی یا خصیصه داشت (فیلد) و یا یک سری کارکرد و اتفاق داشت (متد). همچنین مفهوم ارث بری آشنا شدید. کلاسی که از آن ارث برده میشد یعنی کلاس پدر را super class و کلاسی که ارث برده یعنی کلاس فرزند را subclass میگوییم.

در ارث بردن تمام فیلدها و متدهای public از superclass به subclass به ارث میرسند. همچنین میتوانستیم برخی از متدهای superclass را در کلاس فرزند تغییر دهیم با Override کردن.

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

خب برگردیم به اندروید یک لحظه.

نکاتی که گفته شد رو کجاها دیدیم. مثلا در اکتیویتی. ابتدا کلاسی میساختیم. برای اینکه این کلاس تبدیل به اکتیویتی شود از آن ارث میبردیم

Public class MyActivity extends Activity

در ادامه متد onCreate را داشتیم. در ابتدای این متد مینوشتیم @Overrid که تعیین کننده بازنویسی این متد در کلاس فرزند یعنی MyActivity هست. همچنین داخل این متد از super استفاده کرده ایم

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
}

دلیلش این هست که در داخل onCreate در یک اکتیویتی (کلاس اکتیویتی) مسلما کدهای زیادی قرار دارد و اتفاقات زیادی می­افتد. پس ابتدا باید بخواهیم که متد onCreate اصلی در کلاس اکتیویتی کدهایش اجرا شود تا درواقع اکتیویتی ما به حالت create برود. پس از آن کدهای خودمان را در ادامه می­نویسیم.

*کلاس های انتزاعی

تا اینجای کار یک دوره و یادآوری بود. اما نوعی از کلاس ها هست که به آن اشاره ای نشد. کلاس­های abstract. کلاس های انتزاعی یا abstract کلاس هایی هستند که در اصل نمیتوان از آن شی ساخت (نمونه گرفت). اما کاربردشان چیست.

بدنه کلی این کلاس ها به صورت زیر هست:

abstract class AbstractClass {
    
    //something
    
}

خب بیاید با یک مثال این مفهوم را متوجه شویم. فرض کنید برای حساب های بانکی داریم برنامه ای مینویسیم. کلاسی داریم برای حساب های بانکی بلند متد و کلاسی برای حساب های بانکی کوتاه مدت.

Public class ShortTimeAccount{
String AccountNo;
Double Amount;

public double benefit(){
return amount*0.10;
}
}


Public class LongTimeAccount{
String AccountNo;
Double Amount;

public double benefit(){
return amount*0.20;
}}

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

Public class Account{
String AccountNo;
Double Amount;
}
Public class ShortTimeAccount extends Account{
public double benefit(){
return amount*0.10;
}}
public class LongTimeAccount extends Account{
public double benefit(){
return amount*0.20;
}}

مسلما این کار خیلی اصولی تر خواهد بود. اما متد benefit هم خوب میشد که در کلاس Acount قرار بگیرد. اما میبینید که محتوای آن فرق میکند. از طرفی استفاده از شی از نوع Account ممنوع هست زیرا چنین شی ای نداریم. اشیای ما یا باید حساب بلند مدت باشند یا کوتاه مدت. و چیزی به نام Account وجود ندارد. در چنین مواقعی میتوانیم از کلاس های abstract استفاده کنیم. 

Public abstract class Account{
String AccountNo;
Double Amount;
Public abstract double benefit();
}

همانطور که گفتم نمونه گرفتن دیگر از این کلاس ممکن نیست ینی چنین چیزی نخواهیم داشت:

Account a = new Account()

از طرفی در اینجا یک مدل جدیدی از متد میبینید! متدی که نام، و نوع خروجی (و اگر لازم بود نوع ورودی) را خواهد داشت. اما بدنه ندارد! در اصل بیان این متد اینجا تعیین میکند که تمام کلاس هایی که ارث میبرند از Account باید این متد را پیاده کنند خودشان و دقیقا همین نام و همین نوع ورودی و خروجی را داشته باشد. این متدها باید حتما در کلاس فرزند پیاده شوند. البته کلاس های abstract میتوانند متدهای عادی هم داشته باشند. که البته احتیاجی به پیاده سازی شان در کلاس فرزند نیست. تا همین حد کافی هست برای مطالعه بیشتر میتوانید آموزش های جاوا را پیگیری کنید 

اما برای چی اینجا بحث abstract را گفتیم. چون نیاز بود مفهوم دیگری به نام interface را بدانید. در اصل برای تعریف یک interface باید به جای کلمه class از کلمه interface استفاده کنید.

*اینترفیس ها

public interface MyInterface {

}

اینترفیس ها مثل کلاسهای انتزاعی هستند اما تفاوت هایی دارند. در اینترفیس هرچه را که بیان کردیم در کلاس فرزند باید پیاده شود. از طرفی  ارث بری از اینترفیس ها با کلمه کلیدی implements صورت میگیرد. از اینترفیس­ها نیز مثل abstract ها نمیتوان نمونه گرفت.

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

public void my method(){}

با خطایی روبرو میشویم که متدها در اینترفیس نمیتوانند بدنه داشته باشند. حتی اگر خالی باشد. و عنوان آنها را مثلا به شکل زیر میتویسیم:

public void my method();

 و در نهایت این تفاوت که در ارث بردن، یک کلاس فقط میتواند از یک کلاس دیگر ارث ببرد.

چه در حالت عادی، و چه در این حالت که کلاس پدر abstract باشد.

اما در مورد اینترفیس ها یک کلاس میتواند از چندین اینترفیس implement کند.

public class class1 implements MyInterface,MyInterface2{
    
}

و در نهایت یک نکته جالب. درست هست که بطور علمی میگیم از abstract ها و interface ها نمیتوان نمونه گرفت (object ساخت). اما نشدنی نیست. بلکه شما بارها این کار را انجام دادید.

نکته ای که همیشه از آن گذشتیم ایجاد متد onClick بود. بگذارید مثالی بزنیم تا آشنا شوید.

فرض کنید در برنامه اندرود(یا جاوای) خودم یک interface ساختم به نام MyInterface.

آموزش برنامه نویسی اندروید قسمت شانزدهم

حالا وارد کلاس دیگری میشویم. بدون implement کردن این اینترفیس میخواهم از آن شی بسازیم.

آموزش برنامه نویسی اندروید قسمت شانزدهم

خب حالا روی همین اولین گزینه ای که میبینید (در autocomplete ) کلیک کنید. و نتیجه:

آموزش برنامه نویسی اندروید قسمت شانزدهم

به همین سادگی. حال وظیفه شما پیاده سازی این متدها هست! نمونه این را کجا دیدیم؟ در موقع پیاده سازی متد onClick

آموزش برنامه نویسی اندروید قسمت شانزدهم

دقیقا شما در حال object ساختن از OnClickListener هستید! در اصل ورودی متد setOnClickListener یک اینترفیس هست. که آن را بعنوان ورودی میدهیم. میتوانیم این کد را بصورت باز شده در شکل زیر ببینیم:

آموزش برنامه نویسی اندروید قسمت شانزدهم

*مفهوم Thread

خب رسیدیم به مفهومی که تا الان در حال دنبال کردن مقدماتش بودیم. با مفهوم thread آشنا شدید تا حدی. بطور ساده بخوام بیان کنم حتما میدانید که سیستم عامل که کنترل سیستم شما را در دست دارد برای اینکه بتوانید چندین برنامه را باهم اجرا کنید، در هرلحظه قسمتی از برنامه ها را به cpu میدهد تا این برنامه ها لابه لای هم اجرا شوند. و سرعت جابه جایی بین این لایه ها انقدر سریع هست که شما فرض میکنید این برنامه ها در زمان واحد درحال اجرا هستند. اما علاوه بر این امکان، شما میتوانید برنامه هایتان را نیز به بخش های کوچکی به نام thread تقسیم کنید. و بخواهید که این بخش ها بصورت موازی اجرا شوند. و به اصطلاح از قابلیت multiThreding استفاده کنید. شکل زیر تفاوت این دو نوع را نشان میدهد:

  در اندروید Thread

برای پیاده سازی thread در جاوا، از کلاس thread و اینترفیس Runnable استفاده میکنیم. برای نوشتن یک Thread میتوانیم از کلاس Thread ارث برده و یا اینترفیس Runnable را implement کنیم. خب بیاید یک مثال بزنیم برای Runnable.

Public Class MyThread implements Runnable{
Public void run(){
//Do something in thread
}}

و حالا برای راه اندازی این کلاس کافی است در متد run که به همراه اینترفیس Runnable آمده است کاری که میخواهید در زمان اجرای Thread صورت بگیرد را بنویسید.. در نهایت برای اجرای این thread به کد زیر نیاز است. این کلاس را بعنوان ورودی به کلاس Thread میدهید. سپس از متد start برای راه اندازی آن استفاده میکنید.

آموزش برنامه نویسی اندروید قسمت شانزدهم

در این کلاس من از متد sleep استفاده کردم و در آن خواستم 5000 میلی ثانیه یا در اصل 5 ثانیه کد من در این نقطه توقف کند. این متد چون ممکن است دچار Exception شود باید آن را داخل try catch بگذارید.

پس از آن توقف برنامه متنی را چاپ میکند. پس از اجرای این کد میبینید که پس از 5 ثانیه این متن برای شما چاپ میشود و البته اگر شما کار دیگری در برنامه را در حال انجام داشته باشید تداخلی باهم نخواهند داشت و کار دوم شما روال خودش را ادامه میدهد.

حال در کلاس دیگری این Thread را اجرا میکنم.

 

پس از آن توقف برنامه متنی را چاپ میکند. پس از اجرای این کد میبینید که پس از 5 ثانیه این متن برای شما چاپ میشود و البته اگر شما کار دیگری در برنامه را در حال انجام داشته باشید تداخلی باهم نخواهند داشت و کار دوم شما روال خودش را ادامه میدهد.

حال در کلاس دیگری این Thread را اجرا میکنم.

آموزش برنامه نویسی اندروید قسمت شانزدهم

پس از Run کردن این کلاس test میتوانید ببینید بعد از 5 ثانیه متن شما چاپ میشود.

اما امروز کار دیگری را یاد گرفتیم. اینکه بدون implement کردن یک اینترفیس از آن استفاده کنیم. کار سختی نیست. کد زیر را ببینید:

آموزش برنامه نویسی اندروید قسمت شانزدهم

خب و در نهایت استفاده از چیزهایی که یاد گرفتیم برای تکمیل بحث Splash. دیدید که یک کد ساده میتونست چقدر پیش نیاز داشته باشه!

در اندروید برای ایجاد ارتباط بین thread و ui از همگام سازی بنام Handler استفاده میکنیم. این کلاس خودش متدی به نام postDelay دارد که دو ورودی میگیرد. ورودی اول یک اینترفیس Runnable و ورودی دوم میزان زمانی که میخواهید وقفه بیندازید .

آموزش برنامه نویسی اندروید قسمت شانزدهم

در اصل این کد را اگر بخواهم باز کنم بصورت زیر هست:

آموزش برنامه نویسی اندروید قسمت شانزدهم

به همین سادگی خسته نباشید