توسعه اپلیکیشن: چگونه میتوان 13 خطای رایج در اندروید را برطرف کرد؟ – بخش سوم
در دو مطلب قبلی به چندین خطای رایج در اندروید و راه حل آنها پرداختیم، در ادامه شما را با سایر خطاها آشنا میکنیم، با ما همراه باشید.
9. Application Not Responding Error
این خطا به صورت یک دیالوگ در گوشی اندروید یا AVD که برای تست اپلیکیشن از آن استفاده کردید، ظاهر میشود. خطای Application Not Responding یا همان ANR زمانی بوجود می آید که رابط کاربری اپلیکیشن فریز میکند و برای بیش از 5 ثانیه هیچ واکنشی به ورودی کاربر نشان نمیدهد. معمولا این شرایط زمانی اتفاق می افتد که اپلیکیشن عملیات طولانی یا فشرده ای را در ترد اصلی رابط کاربری اندروید اجرا کند.
ترد اصلی رابط کاربری در اندروید، مسئول توزیع تمامی ایونت های ورودی کاربر به ویجت های رابط کاربری مناسب و آپدیت کردن رابط کاربری اپلیکیشن میباشد. این ترد تنها قادر به انجام یک تسک در یک مدت زمان خاص میباشد، بنابراین اگر با این عملیات زمانبر و فشرده ترد اصلی را مسدود کنید، رابط کاربری تا تکمیل عملیات، واکنش گرایی خود را از دست میدهد.
در صورتیکه هنگام تست اپلیکیشن با پیام ANR مواجه شدید، باید عملیاتی را که در ترد اصلی انجام میدهید مورد بررسی قرار دهید. چنانچه صریحا این خطا را دریافت نمیکنید، اما اپلیکیشن گاهی اوقات کند میشود و تاخیر دارد، احتمال مواجه شدن با خطای ANR زیاد است و باید وضعیت ترد رابط کاربری را بررسی کنید.
برای برطرف کردن خطاهای ANR، باید تمامی اپلیکیشن هایی را که مستعد اجرای کند بوده یا به قدرت پردازش قابل توجهی نیاز دارند را شناسایی کرده و از ترد اصلی حذف کنید. برای این کار یک worker thread بسازید که احتمال مسدود کردن ترد اصلی رابط کاربری به صفر برسد.
برای ساخت تردهای اضافه چندین متد وجود دارد، اما ساده ترین راه حل استفاده از یک AsynTask میباشد که این کلاس شامل worker thread خود و یک فرخوانی ()onPostExecute میباشد که میتوانید برای ارتباط با ترد اصلی رابط کاربری اندروید از آن استفاده کنید.
با این حال AsynTaskها برای اجرای عملیات پس زمینه کوتاه گزینه مناسب تری میباشند، لذا برای عملیات طولانی بهتر است از یک Service یا IntentService استفاده کنید.
حذف تسک های زمانبر و فشرده از ترد اصلی تاثیر چشمگیری بر روی عملکرد اپلیکیشن خواهد گذاشت، اما بهترین روش برای اجرای کمترین عملیات ممکن بر روی ترد اصلی رابط کاربری میباشد. حتی اجرای حجم کوچکی از کدهای غیرضروری در ترد اصلی نیز بر روی واکنش گرایی اپلیکیشن تاثیرگذار است، لذا وقتی تمامی عملیات زمان بر و فشرده را حذف کردید، باز باید بررسی کنید که اگر کد دیگری باقی مانده که باید از ترد اصلی حذف کرد، این کار را انجام دهید.
10. Only the Original Thread That Created a View Hierarchy Can Touch Its Views
در اندروید، تنها از طریق ترد اصلی قادر به آپدیت کردن رابط کاربری هستید. اگر بخواهید از طریق سایر تردها به اجزای رابط کاربری دسترسی پیدا کنید، به این خطا بر خواهید خورد.
برای برطرف کردن این مشکل، بخشی از تسک پس زمینه را که در حال آپدیت کردن رابط کاربری است شناسایی کرده و آن را به یک runOnUiThread منتقل کنید، برای مثال:
runOnUiThread(new Runnable() {
@Override
public void run() {
//Update your UI//
}
});
به جای این کار میتوانید از یک handler استفاده کرده یا عملیات پس زمینه را در یک AsynTask اجرا کنید، برقراری ارتباط با ترد اصلی از طریق فراخوانی متد ()onPostExecute صورت میپذیرد. در صورتی که جابجا شدن بین تردها زیاد شده، باید از یک لایبرری به نام RxAndroid استفاده کنید، این لایبرری شما را قادر به ساخت یک ترد جدید، برنامه ریزی عملیاتی که باید بر روی این ترد انجام شوند و ارسال نتیجه به ترد اصلی میکند و تمامی این کارها تنها با چند خط کد امکان پذیر است.
11. NetworkOnMainThreadException
این خطا زمانی بوجود می آید که اپلیکیشن شما بخواهد عملیات شبکه مانند ارسال درخواست های API، متصل شدن به یک پایگاه داده ریموت، دانلود کردن یک فایل و غیره را در ترد اصلی انجام دهد. زمانبر بودن عملیات شبکه احتمال مسدود شدن ترد اصلی را بالا میبرد و در نسخه 3.0 و بالاتر از اندروید، زمانی که بخواهید یک درخواست شبکه در ترد اصلی ارسال کنید، با این خطا روبه رو میشوید.
در صورت مواجه شدن با NetworkOnMainThreadException، کد شبکه ای را که بر روی ترد اصلی اجرا میشود پیدا کرده و آن را به یک ترد مجزا منتقل کنید.
اگر لازم است درخواست های شبکه مکرری ارسال کنید، باید از Volley استفاده کنید که یک لایبرری HTTP برای تولید تردهای پس زمینه است، با این کار تمامی درخواست های شبکه به طور پیشفرض از ترد اصلی حذف میشوند.
12. Activity Has Leaked Window That Was Originally Added Here
این خطا زمانی بوجود می آید که بعد از خروج از یک اکتیویتی، بخواهید یک دیالوگ را نمایش دهید. اگر به این مشکل برخوردید، باید متد ()dismiss را در متد ()onDestroy یا ()onPause اکتیویتی فراخوانی کنید تا مطمئن شوید که دیالوگ را به درستی بسته اید، برای مثال:
@Override
protected void onDestroy()
{
super.onDestroy();
if(pDialogue!= null)
pDialogue.dismiss();
}
13. OutofMemoryError
این خطا زمانی رخ میدهد که اپلیکیشن یک درخواست حافظه ارسال کند که امکان آن برای سیستم وجود نداشته باشد. در صورت مواجه شدن با این خطا باید از تمامی اشتباهات رایج در مدیریت حافظه جلوگیری کنید و تمامی دریافت کننده های برادکست را آنرجیستر کرده و تمامی سرویس ها را متوقف کنید. مطمئن شوید که در متغیرهای استاتیک، رفرنس نگه نمیدارید و بیت مپ های حجیمی را بارگذاری نمیکنید.
اگر تمامی دلایل مشهود برای OutofMemoryError را برطرف کردید، باید بررسی را ادامه دهید تا بفهمید تخصیص حافظه در اپلیکیشن به چه شکلی صورت میپذیرد، زیرا احتمال دارد بتوانید مدیریت حافظه اپلیکیشن را در بخش هایی بهبود دهید.
در اندروید استودیو یک بخش کامل به تحلیل مصرف حافظه اپلیکیشن اختصاص داده شده، برای این کار باید از نوار ابزار اندروید استودیو به View> Tools مراجعه کنید. در این مرحله گزینه Android Monitor یا Android Profiler را مشاهده میکنید که به نسخه اندروید استودیو که نصب کرده اید بستگی دارد.
حال نگاهی به امکانات اصلی Android Profiler می اندازیم.
با باز کردن Android Profiler، سه بخش از اطلاعات به طور خودکار ثبت میشود.
از آنجه که نحوه استفاده از حافظه در اینجا برای ما مهم است، باید بر روی بخش Memory کلیک کنید که Memory Profiler اجرا شود.
Memory Profiler شامل یک تایم لاین است که انواع گوناگونی از حافظه که هم اکنون توسط اپلیکیشن تخصیص داده شده را نمایش میدهد، برای مثال جاوا، نیتیو و استک. در بالای این نمودار چندین سطر آیکون را مشاهده میکنید که با کلیک کردن بر روی هریک از آنها عملیاتی اجرا خواهد شد.
- اجرای ایونت garbage collection
گرفتن عکس Hprof از حافظه اپلیکیشن، که تصویری از تمامی آبجکت های درون پشته اپلیکیشن مانند نوع آبجکت هایی که اپلیکیشن شما تخصیص داده، تعداد آبجکت های تخصیص داده شده و مقدار فضایی که این آبجکت ها اشغال میکنند، میباشد.
ثبت تخصیص های حافظه. با ثبت تخصیص های حافظه اپلیکیشن هنگام اجرای عملیات خاص، شما قادر به تشخیص عملیات خاصی که حافظه زیادی مصرف میکنند، میگردید.
- برای شناسایی بخش هایی از اپلیکیشن که مسئول OutOfMemoryError هستند، کمی با اپلیکیشن کار کنید و ببینید در واکنش به عملیات مختلف، چه تغییری در تخصیص حافظه بوجود می آید.
زمانی که بخشی از پروژه را که مشکل زا است شناسایی کردید، نشتی حافظه و هرگونه ناکارآمدی در نحوه استفاده از حافظه را مورد بررسی قرار دهید.