همه چیز راجع به سرویس ها در اندروید (۱_۲)

 (نکات تکمیلی ، ANR ، Crash ، Service و Thread)
سطح:پیشرفته

تفاوت ANR و Crash چیست؟
ANR : ANR مخفف Android Not Responding است . همانطور که میدانید تمامی پردازش های رابط کاربری و ظاهر و UI یک اپلیکیشن در Thread (نخ) اصلی و واحد آن انجام می شود. ANR زمانی رخ می دهد که ما یک پردازش طولانی مدت (چیزی حدود ۵ ثانیه)  را در ترد  اصلی UI انجام دهیم.
که این باعث می شود تا (GUI(Graphic User Interface برنامه قفل شود و دیگر هیچ واکنشی نشان ندهد. در این صورت یک دیالوگ ظاهر می شود که از شما میخواهد یا Wait را انتخاب کنید تا شاید برنامه بتواند خودش را بازیابی کند و مجددا اجرا شود و یا Force Close را انتخاب کنید تا از برنامه خارج شود.

Crash :Crash که در لغت به معنای درهم شکستن است ناشی از یک Exception و یک error مدیریت نشده است .(منظور از مدیریت نشده این است که درون try/catch نباشد )  مثل وقتی که در برنامه یک عدد را بر صفر تقسیم کنیم یا محاسبات ریاضی بین یک رشته از حروف و یک عدد انجام دهیم یا وقتی یک آرایه ی خالی را پیمایش کنیم و…  که منجر به Crash و در نهایت Force Close برنامه می شود و معمولا از روی نوع Exception میتوان به علت خطا پی برد.

اکنون میخواهیم کاری کنیم تا در سرویس مان پروسه ای طولانی انجام شود تا منجر به خطای ANR شود .
در صفحه ی activity_main.xml همانطور که در آموزش قبل گفتیم  دو دکمه برای شروع و توقف سرویس داریم و در MainActivity.java هم دستورات StartService و StopService را برای آنها می نویسیم.
در سرویس مان برای ایجاد خطای ANR  ، هر دو ثانیه یک بار Thread.sleep را در یک حلقه ی for تا ۱۰۰ مرتبه صدا میزنیم و به ازای هر اجرای حلقه یک Log به صورت زیر  چاپ میکنیم:
<<تابع Thread.sleep عددی را بر حسب میلی ثانیه میگیرد و می توان گفت که یک پردازش را به همان میزان شبیه سازی میکند و این طبیعی است که اگر یک محاسبات و پردازش طولانی مدت در Thread اصلی داشته باشیم حافظه کم می آورد . شما همچنین می توانید for  را بردارید و یک Thread.sleep طولانی بنویسید (مثلا ۹ ثانیه) .>>

در امولاتور من وقتی به مقدار ۹ رسید دیالوگ ANR ظاهر شد:(در عکس زیر دقت کنید دکمه Start به حالت فشرده باقی مانده است که حاکی از آن است که GUI قفل شده است و هیچ کاری نمیتوان انجام داد تا پروسه تمام شود)

سرویس بدون Thread

خب راه حل چیست؟بله. سرویس مان را در یک Thread دیگر مینویسیم و بار دیگر اجرا میکنیم:(قسمت های زرد را به قسمت قبل اصافه کنید)

Thread در یک سرویس

این بار می بینید که تا عدد آخر یعنی ۹۹ را بدون هیج خطایی در Log چاپ خواهد کرد. 

سوال: Service را Start می کنیم و شروع به چاپ کردن Log در یک Thread دیگر می شود ، اگر در همین حال Service را Stop کنیم چه اتفاقی می افتد؟ آیا عملیات چاپ شدن Log متوقف می شود؟
خیر، شما در متد  onStartCommand  گفته اید برو در یک Thread دیگری به جز Thread ظاهری UI و حلقه ی For را اجرا و Log ها را چاپ کن.
اکنون سرویس را Stop می کنید از onStartCommand خارج می شود و onDestory را اجرا میکند و خودش را از بین می برد اما در یک Thread دیگر دستور شما تا پایان یافتن آن ادامه خواهد داد و تنها راه متوقف سازی آن Force Close کردن اپلیکیشن هست.
یک کار جالب:
سرویس را Start کنید و بگذارید Log ها را جاپ کند کمی که گذشت آن را Stop کنید و مجددا Start بزنید. مشاهده خواهید کرد که دو حلقه ی for در دو Thread مختلف همزمان در حال چاپ شدن هستند و تا پایان نیابند متوقف نخواهند شد مگر اینکه اپلیکیشن را ForceClose کنید.

شما همچنین ممکن است پست های زیر را دوست داشته باشید:

پاسخ دهید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *