Trace رویدادهای چرخه حیات با Logcat
در این درس از دوره توسعه برنامههای اندروید، به بررسی کامل چرخه حیات Activity پرداخته شده و نحوه ردیابی دقیق این رویدادها با استفاده از ابزار Logcat در Android Studio آموزش داده میشود. ابتدا مراحل مختلف چرخه حیات مانند onCreate()
, onStart()
, onResume()
و دیگر متدهای کلیدی معرفی میشوند. سپس نحوه استفاده از دستورات Log.d()
برای ثبت و مشاهده پیامهای مربوط به هر مرحله در Logcat توضیح داده میشود تا بتوانید رفتار برنامه خود را در زمان اجرا تحلیل کنید. این درس به شما کمک میکند درک عمیقتری از مدیریت وضعیت Activityها در طول چرخه حیات به دست آورید و ابزار Logcat را به عنوان یکی از حیاتیترین امکانات برای Debugging در توسعه اندروید به کار بگیرید. با مشاهده ویدیو، نحوه پیادهسازی این مفاهیم را به صورت عملی خواهید آموخت.
اندروید یک محیط برنامه نویسی مبنی بر رویداد است. دررواقع زمانی که کاربر یا سیستم عامل و یا چهارچوب یا همان فریم وورک برنامه، فعالیتی انجام میدهد، کد جاوا مربوط به اون فعالیت اجرا میشود تا نتیجه مورد نیاز برگردانده بشود. برای اینکه شما این اتفاقات رو در کدتان trace کنید و ببینید چه اتفاقی روی دستگاهتان و در برنامه شما میافتد، ما از یک ابزاری به نام log cat استفاده میکنیم، که در Android SDK ساخته شده و در اندروید استودیو هم بصورت یکپارچه وجود دارد.
همانطور که می بینید، من یک پروژه به نام Lifecycle Events باز کردم و در این پروژه میبینید که main activity تقریباً خالی است.
به علاوه در فولدر منابع یعنی همین پوشه res، تنها یک فایل لایوت با نام Activity_main.xml وجود دارد که اون هم می بینید بطور باور نکردنیای خیلی ساده هست. اگر از این پایین تب text رو انتخاب کنم، میبینید که فقط یک ظرف Relative Layout و یک Text View برای کنترل نحوه نمایش متن، دارد. من برای ساخت این اکتیویتی از قالب empty activity بجای قالب blank activity استفاده کردم. همانطور که میدانید قبلاً در ویدئوهای آموزشی خود از قالب blank activity استفاده میکردم. در واقع این سادهترین راه برای کار کردن با برنامه های اندرویدی ساده هست.
کلاس Main Activity فقط شامل متد on Create هست و همانطور که قبلاً هم توضیح دادم، این متد به صورت خودکار وقتی اکتیویتی ساخته میشود و روی صفحه نمایش نشان داده میشود، اجرا میشود.
برای trace آن در کد از کلاسی به نام Log استفاده میکنم، که عضو پکیج android .util هست.
وقتی این کلاس رو انتخاب کنم خودش آنرا کامل میکند و می بینید که بصورت خودکار عبارت و دستورات مربوط به ایمپورتهای این کلاس Log من، در کلاس Main Activity اضافه میشود.
در واقع کلاس Log فقط زمان تست و توسعه برنامه های شما استفاده میشود و وقتی که خواستید برنامه خودتان را بیرون بدهید، باید برگردید به اینجا و کدهای مربوط به این کلاس رو کامنت کنید؛ یعنی اینکه آنها را مخفی کنید و یا اصلاً از تمام منابعِ مربوط به این کلاس آنها را پاک کنید.
کلاس Log یک مجموعه متد دارد که میتوانید با استفاده از فرآخوانی اونها چه از طریق خط فرمان یا همان command line و چه از طریق محیط ویژوالی Android Studio؛ پیامهایی رو به کنسول log cat بفرستید. همانطور که میبینید هر کدام از این متدها یک تک کاراکتر خاص دارند:
d برای debug، e برای error، i برای info و غیره. به اینها لول های دیباگ میگویند. بهتر است از مترادف فارسی آنها یعنی سطوح اشکال زدایی استفاده نکنیم و همان لول های دیباگ بنظر مناسبتر است. من اونها رو وقتی که وارد کنسول log cat بشوید، نشان تان میدهم که چطور میتوانید پیام ها رو مطابق با سطح دیباگ خاصی که میخواهید و حتی لول بالاتر آن هم فیلتر کنید.
میخواهم الان از متد با کاراکتر d برای پیام دیباگ استفاده کنم.
خب؛ مثل بقیه متدها دو تا آرگومان string میخواهد. در واقع برای هر پیامی یک تگ لازم دارید که بتوانید با پیدا کردن اون تگ پیام مربوطه را ببینید و بخوانید. با اینکار میتوانید پیام ها را فیلتر کنید تا پیامهای شما فقط برای این تگها نشان داده بشوند. یک روش رایج برای نوشتن تگ messages استفاده از نام کلاس جاری است.
پس من به عنوان تگ این پیام، Main Activity رو تایپ میکنم.
بعد برای متن پیام هم، از نام متد on Create استفاده میکنم. درواقع میخواهیم بفهمیم که این متد چه زمانی فراخونی میشود.
خب حالا، برنامه ام را برای بار اول روی دستگاهم اجرا میگیرم.
همانطور که برنامه روی دستگاه اجرا میشود، میبینم که خروجی log cat ام در بکگراند بالا میآید.
خب به اندروید استودیو برمیگردم، الان در پنجره Android Monitor هستم.
میتوانید این پنجره رو با کلیک روی تب مربوطه درست پایین گوشه سمت چپ بر روی عبارت Android Monitor و یا با فشار دادن کلیدهای میانبرش که در محیط ویندوز کنترل و 6 و در محیط مک کامند و 6 هست؛ باز و بسته کنید.
خروجی log cat شما شامل یک تعداد زیادی پیام هست که خیلی از آنها نیاز به دقت ندارند، ولی اینجا همان پیام مورد نظر ما هست که تگ Main Activity دارد.
حالا برای فیلتر آن هم، اینجا کلیک میکنم و تایپ میکنم Main Activity، تا فقط پیام هایی که این رشته رو دارند ظاهر بشوند.
این جایی است که لول های log فیلتر میشوند.
وقتی آنرا میگذاریم روی حالت Verbose، در واقع میخواهم که فقط پیام های طولانی نشان داده بشوند. گزینه debug هم پیام های دیباگ را نشان میدهد.
اگر من فیلتر کردن رو بخواهم ادامه بدهم و از فیلترهای مختلف اینجا بخواهم استفاده کنم، ممکن است این پیامها حذف بشوند، چون ممکن است پیامی که مثلاً log لول info، با رشته Main Activity رو بصورت مشترک داشته در این پیام های logcat وجود نداشته باشد.
برمیگردم و Debug رو انتخاب میکنم و دوباره می بینید که یک پیام نشان داده میشود.
روش های دیگری هم برای تگ دادن به پیامها وجود دارد.
یک روش استفاده از برخی کدهای جاوا، برای گرفتن خروجی نام کلاس جاری هست.
میتوانم از متد get Class برای نامگذاری کلاس جاری استفاده کنم و بعد از لیست اونget SimpleName رو فراخونی کنم و این کد جزیی از دستورات گرامری جاوا یا یکJava syntax هست و به صورت پویا نام کلاس جاری رو بر میگرداند.
بعد از اعمال تغییرات، دوباره اجرا میگیرم و دوباره در خروجی log cat ام دقیقاً همان تگ قبلی را میبینم.
یک روش دیگر ساخت یک مقدار ثابت هست.
یکبار دیگر رشته Main Activity رو تایپ میکنم و اون رو جایگزین این Java syntax میکنم و این رشته رو بصورت هایلایت درست از قبل کوتیشن ها انتخاب میکنم و از قسمت منوها گزینه Refactor رو انتخاب میکنم بعد Extract و بعد Con stant رو کلیک میکنم.
من نام constant یا ثابت خود را به LOG، underscore، TAG تغییر میدهم.
حالا یک ثابت رشتهای ایجاد کردم؛ ثابتهای رشته ای از زمان تعریف تا موقع استفاده از آنها ثابت میمانند و تغییر نمیکنند و اینجا از آن استفاده میکنم.
و میتوانم دوباره در قسمتهای دیگر این برنامه هم از آن استفاده کنم.
خب؛ این از متد on Create. حالا بقیه متدهای چرخه حیات (life-cycle method) رو که در ویدیوی قبلی اشاره کردم امتحان کنیم.
دو تا رویداد دیگری که در زمان start up یک اکتیویتی رخ میدهند on Start وon Resume هستند. برای هر کدام از اینها، اول نام متد رو تایپ میکنم، و اندروید استودیو امضا کامل آنرا نشانم میدهد؛ میبینید که کدم یک متد Override هست و می دانید کاربرد Override هم این است که کلاس پدر رو تعریف کند؛ پس انتخاب این رویداد on Start فراخوانی یک نسخه متد از کلاس والد یا super class هست.
وقتی من on Start رو از این لیست انتخاب کنم، متد با تیتر Override به کدم اضافه میشود.
یک کپی از این کد میگیرم و این پایین درست در اینجا آنرا پاست میکنم و نام رویداد رو ازon Create به on Start تغییر میدهم.
اجازه بدهید این پنجره رو ببندم که فضا بیشتری در اختیار داشته باشم و متد on Resume رو ایجاد میکنم.
یکبار دیگر اون کد رو پاست میکنم و پیامش را به on Resume تغییر میدهم.
حالا میتوانم از کدم ران بگیرم.
صبر میکنم تا برنامه من لود بشود و برمیگردم به خروجی log cat ام و میبینم که همانطور که پیش بینی کرده بودم این رویدادها به ترتیب اول on Create بعد on Start و on Resume اجرا شدند.
حالا بیایید دو تا متد دیگر از چرخه حیات اکتیویتی اضافه کنیم.
وقتی یک اکتیویتی بسته میشود متد on Pause اتفاق میافتد و همچنین متد on Stop هم فراخوانی میشود.
من این دو تا متد on Pause و on Stop رو هم به پیامهایم اضافه میکنم و دوباره از برنامه اجرا میگیرم.
کمی صفحه نمایش را تنظیم میکنم تا درست ببینم چه اتفاقی میافتد. صفحه اندروید استودیو رو به سمت چپ درگ میکنم و صفحه نمایش دستگاهم را هم میاورم سمت راست.
بعد روی تب Android Monitor دابل کلیک میکنم تا بزرگ بشود تا فقط خروجی log cat قابل دیدن بشود. مثل قبل موقع بالا اومدن اکتیویتی روی صفحه نمایش رویدادهای Start، Create و Resume اتفاق میافتند.
حالا نگاه کنید وقتی از برنامه خارج میشوم، با فشار دادن دکمه back روی دستگاه چه اتفاقی میافتد.
میبینم on Pause و on Stop هم ظاهر میشوند.
در واقع با shut down اکتیویتی و بستن برنامه این دو متد on Pause و on Stop اجرا میشوند.
من دوباره برنامه رو با لمس آیکن لانچر مربوط به برنامهام در لیست برنامههای دستگاه اجرا میکنم و یکبار دیگر متدهای onCreate، onStart و on Resume اجرا میشوند.
اینبار بجای لمس دکمه back دکمه home رو لمس میکنم.
یکبار دیگر میبینیم که on Pause و on Stop اجرا میشوند.
ولی ایندفعه وقتی برنامهام را از لیست برنامههای دستگاه انتخاب کنم، البته اینجا دقت کنید برنامه دیگری انتخاب نکنید؛ ایندفعه فقط متد on Resume اجرا میشود و دیگر on Create اجرا نمیشود. دقت داشته باشید این نکته مهم است که بتوانید فرق بین بستن یک برنامه با فشردن دکمه back و جابجایی بین تسکها با فشردن دکمه home رو تشخیص بدهید. یعنی بفهمید وقتی دکمه back میزنیم چه اتفاقاتی میافتد و چه متدهایی اجرا میشوند و وقتی دکمه home رو میزنیم چی. در مورد اول، کلاً برنامه رو با shut down اکتیویتی بستید و برای اجرا مجدد آن، مجبور هستید دوباره برنامه رو از اول اجرا کنید. وقتی شما دکمه home رو لمس کنید، به صفحه لانچر برگشتید، ولی اون اکتیویتی هنوز در بکگراند موجود است و از مموری حذف نشده. بنابراین وقتی اون رو دوباره اجرا میکنید، فقط میرود روی تسک مربوط به اون برنامه و نیازی نیست که از اول تسک مربوط به اون برنامه ساخته بشود. لازم به ذکر است که چند تا رویداد چرخه حیات دیگر هم وجود دارند که میتوانید trace شان کنید. مثل: on Restart و غیره. توصیه میکنم این متدها رو با کد log cat امتحان کنید، تا با ترتیب اجرا رویدادهای چرخه حیات اکتیویتی آشنا بشوید و متوجه بشوید که در هر زمان چهارچوب یا فریم وورک برنامه و اندروید چه کارهایی در پسزمینه انجام میدهند.