AsyncTask در اندروید


 

asynctask در اندروید - علیرضا پیر

AsyncTask چیست؟

یک task غیر همزمان (Asynchronous) به محاسباتی گفته می شود که در بک گراند انجام شود و نتایجش در Thread UI منتشر شود.

این کلاس این اجازه را به شما می دهد که عملیات بک گراندی را انجام دهید و نتایج آن را در نخِ UI منتشر کنید؛ بدونِ اینکه مجبور باشید با نخ ها یا Handler ها سر و کله بزنید.

AsyncTask به شکل یک کلاس کمکی حولِ Thread  و Handler طراحی شده است و به صورت مجزا یک چهارچوب Threading ارائه نمی کند.

طبق مستندات گوگل، به صورت ایده آل، AsyncTask باید برای عملیات کوتاه استفاده شود (حداکثر چند ثانیه). اگر بخواهید برای مدتی طولانی نخ ها را در جریان نگه دارید، توصیه می شود که از API هایی که داخل پکیج java.Util.concurent ارائه شده استفاده کنید، چیزهایی مثل Executor؛ FutureTask؛ و ThreadPoolExecutor.

Asynctask  برای عملیات زمان بری که فقط یک بار به اجرا نیاز دارند و نمیتوانند در نخ UI انجام شوند طراحی شده است. مثلا دریافت و یا پردازش داده ها وقتی که یک دکمه انتخاب شد مثالِ خوبی از این عملکرد است.

 

 

AsyncTask با Service ها چه تفاوتی دارد؟

همین ابتدا بگویم، مبحث دیگری در اندروید وجود دارد به نام Service ها، آموزش ویدئویی این مبحث را می توانید در آپارات مشاهده کنید.

 

برای افرادی که اندک آشنایی با بحث سرویس ها دارند، ممکن است سوال پیش بیاید که تفاوت سرویس و AsyncTask در چه چیزی است.

 

در بعضی از حالت ها، پیاده سازی یک عمل، با هر دو روش Service و AsyncTask امکان پذیر است. با این حال، معمولا یکی؛ از دیگری بسته به نوع task؛ مناسب تر است.

AsyncTask ها برای به انجام رساندنِ کارهای زمان برِ یک بار رخ دهنده (یعنی کارهایی که فقط یک بار نیاز به اجرا دارند) که نمی توانند در نخِ UI اجرا شوند طراحی شده است. یک مثال متداول برای استفاده از این عملکرد، دریافت و یا پردازش اطلاعات پس از کلیک کردن روی یک دکمه است.

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

 

اگر نیاز داشته باشیم که به صورت مداوم کاری را در بکگراند انجام دهیم، انتخاب Service یک انتخاب درست است. مثال هایی از این می توانند پخش موزیک، و چک کردن برای داده های جدید به صورت مداوم می باشد.

سرویس ها لزوما خارج از نخِ UI اجرا نمی شوند (اگر برایشان یک نخ جداگانه تعریف نکنیم).

در اکثر مواقع؛ service ها برای وقتی هستند که می خواهید یک کد را، حتی اگر اکتیویتی نرم افزار شما باز نیست اجرا کنید. AsyncTask اما برای اجرای بسیار ساده ی  کدها خارج از نخِ UI طراحی شده است.

(توضیح بالا از سایت StackOverflow ترجمه شده است)

 

ساخت و استفاده از AsyncTask

باید از AsyncTask فرزند بسازیم تا بتوانیم از آن استفاده کنیم. این فرزند، حداقل یکی از متدهای موجود در AsyncTask را باید پیاده سازی (override) کند (تابع doInBackground)، البته اغلب اوقات نیاز است تا تابع دومی هم باز نویسی شود (تابع onPostExecute).

مثالی از این فرزند سازی را در زیر می بینیم:

وقتی ساخته شد، استفاده از این task در اکتیویتی بسیار ساده خواهد بود:

اگر دقت کرده باشید، به عنوان ورودی در هنگام ساخت فرزند، در این بخش:

ما سه نوع داده مشخص کرده ایم، به این نوع داده ها، پارامتر های داده های عمومی یا generic types گفته می شود.

این سه نوع داده، به ترتیب Params؛ Progress، و Result نامیده می شود.

 

برای استفاده از AsyncTask، اول ما باید کاری را به انجام رسانیم، دوما مراحل پیشرفت آن کار را به UI اطلاع دهیم و در نهایت نتیجه را به UI برگردانیم، حالا این سه ورودی به ترتیب مشخص می کنند که:

1- نوع پارامتری که قرار است Asynctask به عنوان ورودی تابع doInBackgroundo خود بگیرد تا با استفاده از آن کار را به انجام رساند چه باید باشد.

2- نوع واحدی که حین انجام رساندنِ کار، به عنوان سیگنالِ پیشرفت کار باید به UI ارسال شود چیست؟ (مثلا برای اینکه نشان دهیم چند درصد از دانلود پیش رفته است، شاید رشته یا عدد صحیح انتخاب مناسبی باشد.

3- داده ای که میخواهیم این AsyncTask به عنوان نتیجه برای ما ارسال کند از چه نوعی باید باشد؛ مثلا حجم فایل دانلود شده می تواند با نوع داده ای Long به عنوان نتیجه برایمان ارسال شود.

 

اگر یک یا چند تا از این سه نوع هم در مورد کاری ما استفاده نمی شوند، می توانیم در تعریف به جایشان از Void استفاده کنیم:

 

مراحل اجرای AsyncTask

وقتی یک Asynchronous task اجرا می شود، اجرای task این 4 مرحله را طی می کند:

 

1- onPreExecute: این اولین تابعی است که در حین اجرای تسک اجرایی می شود، این تابع در نخِ UI اجرا شده و برای آماده سازی task استفاده می شود، مثلا فعال کردن نمایش یک ProgressBar در رابط کاربری می تواند مثال خوبی برای کاربرد آن باشد.

2- doInBackground: این تابع در نخِ background (نخی جدا از نخِ UI) و به محص تمام شدنِ اجرایِ onPreExecute اجرا می شود.اینجا جایی است که محاسبات پس زمینه ای که میتواند مدت زمان زیادی نیز طول بکشد انجام می گیرد. نتیجه محاسبات در این مرحله باید برگشت داده شود که این داده return  شده به مرحله آخر ارسال می شود.

این مرحله می تواند از publishProgress هم برای ارسال یک یا چند واحد progress استفاده کند. این مقادیر ارسال شده در نخِ UI منتشر شده و در تابع onProgressUpdate دریافت می شود.

3- onProgressUpdate این تابع در نخِ UI و بعد از اینکه تابع publishProgress فراخوانی شد اجرا می شود. مدت زمان اجرایی شدنِ کامل Task معلوم نیست. به همین دلیل این تابع برای نشان دادن میزان پیشرفت کار در حال انجام در بک گراند به کاربر و در رابط کاربری تعبیه شده است. برای مثال این تابع می تواند برای نشان دادن میزان پیشرفت انجام یک عملیات توسط progressbar یا نمایش Log به کاربر استفاده شود.

4- onPostExecute: این تابع در نخِ UI و پس از اینکه محاسباتِ بک گراند (تابع doInBackground) انجام شد اجرایی می شود. نتیجه برگشت داده شده توسط تابع doInBackground به این تابع به عنوان ورودی ارسال می شود.

 

متوقف کردن اجرای AsyncTask

اینکار می تواند با فراخوانی تابع cancel(boolean) انجام شود. فراخوانی این تابع باعث می شود تا تابع isCanceled در فراخوانی اهی بعدی اش true برگرداند.

بعد از فراخوانی تابع cancel، به جای اجرا شدنِ onPostExecute، تابع onCanceled بعد از return  شدن تابع از طرفِ doInBackgroud فراخوانی می شود.

 

قوانین نخ ها

چند قانون در نخ بندی نرم افزار وجود دارد که برای عملکردِ مناسب در استفاده از این کلاس باید رعایت کنید:

  • کلاس AsyncTask حتما باید در نخِ UI بارگذاری یا load شود.
  • داده ی task (شیء task) باید حتما در نخِ UI تولید شود.
  • اجرایی کردنِ نخ با استفاده از تابع execute باید حتما در نخِ UI انجام شود.
  • توابع onPreExecute، onPostExecute، doInBackground و onProgressUpdate را نباید به صورت دستی فراخوانی کنید.
  • یک task فقط می تواند یک بار اجرا شود، تلاش دوباره برای اجرایی کردنِ یک task برای بار دوم موجب پرتاب یک exception می شود)

قابل رویت بودنِ حافظه ها در AsyncTask

Asynctask تضمین می کند همه فراخوانی ها به صورتی همگام سازی شده که بدون نیاز به پیاده سازیِ یک روند همگام شده مجزا یا جدید، این عملیات امن خواهد بود:

1- مقدار دهی متغیر ها در سازنده یا در تابع onPreExecute و ارجاع به آنها در doInBackground

2- مقدار دهی متغیر ها در doInBackground و استفاده از آنها در onProgressUpdate و onPostExecute.

 

پروژه عملی نحوه کار با AsyncTask

به عنوان پروژه ای ساده برای درک مفهوم عملکردِ AsyncTask، برنامه ای برای دانلود یک فایل از طریق اینترنت ونمایش میزان پیشرفت دانلود را پیاده سازی می کنیم.

ویدئوی مربوط به این آموزش را می توانید در آپارات مشاهده کنید:

 

 

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


2 دیدگاه

  • چاپ مقاله
    چاپ مقاله | 10 آذر, 1397

    تشکر و آرزوي توفيق جاويدان براي شما

    پاسخ
    • علیرضا پیر
      علیرضا پیر | 19 آذر, 1397

      ممنون قربان، انشاألله مفید بوده باشه

      پاسخ

یک دیدگاه بگذارید