استفاده مطمئن از کلاس AsyncTask - خدمات کامپیوتر در محل-پشتیبانی شبکه-راه اندازی شبکه

914 11 11  - 0933
شمال تهران   62 58 31 22 - 021
شرق تهران   31 32 58 77 - 021
تمامی نقاط تهران   01 77 45 88 - 021

 یکی از علت هایی که باعث کرش کردن برنامه میشود زمانی است که از تردها بصورت مطمئن استفاده نمی کنیم. در این مطلب میخواهیم ببینیم چگونه میتوان زمانیکه به تردها احتیاج نداریم آنها را متوقف (یا اصطلاح صحیح تر Cancel) کنیم. در نوشتن این مطلب فرض بر این است که شما با مفهوم ترد آشنایی دارید و تجربه استفاده از آنرا در برنامه هایی که قبلاً نوشته اید، دارید.

 

وقتی برنامه ای در اندروید اجرا میشود، سیستم عامل یک ترد به آن اختصاص میدهد که به نام ترد اصلی برنامه (Main thread) شناخته میشود. در نسخه های جدید اندروید برای اتصال به اینترنت و دریافت دیتا از سرور حتماً باید مراحل اتصال و دریافت در تردی خارج از ترد اصلی برنامه اجرا شود وگرنه خطای Network On Main Thread Exception رخ خواهد داد و برنامه کرش میکند. بنابراین برای اتصال به اینترنت و دریافت دیتا باید تمام مراحل در تردی دیگر انجام شود و نتیجه به ترد اصلی برنامه برگردانده شود.

استفاده از کلاس AsyncTask یک راه کار بسیار مناسب و مطمئن برای اینکار است. قبل از توضیح کلاس بهتر است موضوع را با استفاده از مثالی روشن کنیم. فرض کنیم در یک اکتیویتی یک TextView و یک Button داریم. قرار است با کلیک بر روی دکمه “دریافت” اطلاعات متنی از سرور دریافت شود و در TextView نمایش داده شود.

 مطمئنم با نحوه کدنویسی XML (برای ساخت UI) و لینک کردن آن به کد برنامه مشکل ندارید. بنابراین از آوردن XML صرف نظر میکنم و فقط به قسمت کدبرنامه می پردازم. کد زیر نحوه معرفی دو View فوق به اکتیویتی را نشان میدهد.

حال برای دریافت اطلاعات میبایست تردی دیگر بسازیم که وظیفه آن دریافت اطلاعات از سرور باشد. در کلاس اکتیویتی یک زیر کلاس بنام MyAsyncTask میسازیم که از کلاس AsyncTask مشتق شده باشد. متد ()doInBackground حداقل متدی است که میبایست Override شود. یعنی در این کلاس میبایست حتماً از این متد استفاده شود و سایر متدها اختیاری است. در کد زیر من از سه متد استفاده کردم ام.

متد اول: ()onPreExecute در ترد اصلی برنامه اجرا میشود و زمانیست که بعد از آن از ترد اصلی خارج خواهیم شد. در اینجا بهتر است برای اطلاع کاربر چرخش Progress bar نشان داده شود که کاربر متوجه شود الان درحال گرفتن دیتا از طریق اینترنت هستیم.

متد دوم: ()doInBackground است که در اینجا از ترد اصلی برنامه خارج هستیم. دقت کنید هرگر در این ترد سعی نکنید UI را آپدیت کنید چراکه UI در ترد اصلی برنامه اجرا میشود.

متد سوم: ()onPostExecute است که دوباره به ترد اصلی برنامه برگشته ایم و در اینجا میتوانیم با خیال راحت نتیجه را به کاربر نشان دهیم.

کد زیر را لطفاً مشاهده فرمایید.

 برای اجرای این کلاس کافی است دستور ()new MyAsyncTask().execute را در متد OnClickListener دکمه دریافت دیتا بنویسیم. بدین ترتیب زمانیکه کاربر بر روی دکمه کلیک میکند، کلاس MyAsyncTask اجرا شده و نتیجه دریافت اطلاعات را در صفحه نشان میدهد.

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

فرض کنید کاربر بر روی دکمه “دریافت” کلیک کرد و قبل از اینکه اطلاعات بصورت کامل ار سرور دانلود شود بر روی Back کلیک کرد و به اکتیویتی قبل از این اکتیویتی رفت. در این حالت چه اتفاقی میافتد؟ اگر به مثال فوق برگردیم زمانیکه کاربر با کلیک بر روی Back به اکتیویتی قبل برگشت هنوز ترد در پشت صحنه مشغول دریافت دیتا از سرور میباشد و بعد از برگشت از ترد به متد ()onPostExecute و سپس به متد ()displayData میرسد. در این متد محتویات temp را به textView می دهد تا آنرا نمایش دهد ولی از آنجا که ما درآن اکتیویتی نیستیم بنابراین چیزی از این موضوع نخواهیم فهمید و البته برنامه بدون مشکل به کار خودش ادامه میدهد.

با مثال دیگری مشکل را بررسی میکنیم. فرض کنید در مثال فوق وقتی دیتا را از سرور دریافت کردیم میخواهیم آنرا در دیتابیس ذخیره کنیم. اگر “فیلم آموزشی – فصل نهم دیتابیس” را مشاهده کرده باشید در کد برنامه می بینید که در متد ()onPause دیتابیس بسته شده. حال اگر درحین دریافت دیتا از سرور کاربر بر روی دکمه Back کلیک کند و به اکتیویتی قبل برگردد، ترد بعد از اینکه کارش تمام شد دیتا را به متد ()onPostExecute و سپس به متد ()displayData میدهد. حال که برنامه میخواهد دیتا را در دیتابیس بریزد چون دیتابیس بسته است، برنامه کرش میکند و خطای بسته بودن دیتابیس نشان داده میشود.

حال می بایست دنبال راهکاری بود تا زمانیکه از اکتیویتی خارج شدیم به ترد هم بگوییم متوقف شود. روش کار به اینصورت است که بجای استفاده مستقیم از ()new MyAsyncTask().execute، ابتدا یک آبجکت از MyAsyncTask بسازیم و کد را بصورت زیر تغییر دهیم.

مشاهده می فرمایید که متد ()onPause هم به برنامه اضافه شده که در آن دستور توقف ترد داده شده. حال اگر درحین دریافت دیتا از سرور کاربر بر روی دکمه Back کلیک کند این متد اجرا میشود و دستور توقف به ترد داده میشود. اینکه ترد واقعاً و در لحظه متوقف شود یا نه متاسفانه ضمانتی وجود ندارد و طبق تجربه اینجانب صرف استفاده از دستور cancel باعث متوقف شدن ترد نمی شود. بنابراین به کلاس MyAsyncTask بر میگردیم و کد زیر را به آن اضافه میکنیم.

اینجا چه اتفاقی میافتد؟ اگر ترد متوقف نشده باشد و به کارش ادامه دهد وقتی به (()if(myAsyncTask.isCancelled برسد متوجه میشود که دستور توقف داده شده است. حال که این شرط برقرار است مقدار False در متغییر status قرار میکیرد. این مقدار به متد ()onPostExecute برگردانده میشود و بنابراین دستور (if(result اجازه اجرای متد (displayData(temp را نمی دهد. درنتیجه دیتابیسی هم آپدیت نخواهد شد که  کرش بخواهد اتفاق بیافتد.

نکته آخر اینکه از روش آبجکت سازی (;()MyAsyncTask myAsyncTask = new MyAsyncTask) و استفاده از ()myAsyncTask.execute تنها یک بار در اکتیویتی میتوان استفاده کرد. اگر یک بار ترد را اجرا کردیم و حتی نتیجه را هم ذخیره کردیم، اگر در قسمت دیگری از کد مجدداً ذستور اجرای ترد را بدهیم، برنامه کرش خواهد کرد. علت آن از آنجاکه در مورد موضوع بحث نیست به عهده خودتان گذاشته میشود.

انشالله مطلب مورد استفاده تان واقع شود.

اضافه کردن نظر

کد امنیتی
تغییر کد امنیتی

جهت مشاوره رایگان برای عقد قرارداد پشتیبانی کامپیوتر و شبکه با شماره  22315862 ، 77583231، 88457701  تماس حاصل نمایید .

درباره سرویس رایانه

سرویس رایانه از سال 1387 فعالیت خود را آغاز نموده و آماده ارایه خدمات ذیل (عقد قرارداد پشتیبانی کامپیوتر و شبکه با شرکت ها و موسسات) حتی در روز های تعطیل می باشد :

خدمات ما :

  • راه اندازی و پشتیبانی شبکه های Domain & Workgroup
  • عیب یابی سخت افزاری و نرم افزاری کامپیوتر و لپ تاپ
  • فروش کامپیوتر و قطعات و دوربین مدار بسته
  • فروش و نصب دوربین مداربسته (شبکه یا غیر شبکه) مشاهده از طریق اینترنت و تبلت و موبایل

تماس با سرویس رایانه

راه های ارتباطی جهت مشاوره رایگان و یا عقد قرارداد پشتیبانی شبکه و کامپیوتر :

  • 77583231
  • 88457701
  • 09376320561
  • این آدرس ایمیل توسط spambots حفاظت می شود. برای دیدن شما نیاز به جاوا اسکریپت دارید
  • این آدرس ایمیل توسط spambots حفاظت می شود. برای دیدن شما نیاز به جاوا اسکریپت دارید
جوملا فارسی