چرخه حیات lifecycle اکتیویتی در اندروید
در چرخه فعالیت اکتیویتی ، شما می توانید اعلام کنید که چگونه اکتیویتی شما چگونه و چطور رفتار می کند، زمانی که یکی از اکتیویتی ها از بین می رود و مجدا وارد اکتیویتی می شود. به عنوان مثال، اگر شما در حال ساخت یک پخش کننده ویدیویی هستید، زمانی که کاربر با یک برنامه دیگر، ویدیو را متوقف می کند و اتصال شبکه را قطع می کند. می توانید به شبکه دوباره وصل شود و به کاربر اجازه می دهد تا ویدیو را شروع کند.
چرخه حیات اکتیویتی
زمانیکه با اجرای یک اکتیویتی، اکتیویتی دیگری متوقف میشود، این تغییر از طریق روش های پاسخگویی در چرخه حیات اکتیویتی (activity’s lifecycle callback methods) ، شناخته میشود. چندین روش پاسخگویی برای هر اکتیویتی که ناشی از تغییر در وضعیت آن است، وجود دارد. روشهایی مانند سیستم در حال ساخت اکتیویتی است (creating activity)، در حال متوقف کردن آن است ( stopping activity)، درحال ازسرگیری پردازش است (resuming activity) یا درحال ازبین بردن آن است (destroying activity). بنابراین، هر روش پاسخگویی فرصتی را دراختیارتان میگذارد تا بسته به وضعیت حال حاضر سیستم، عمل خاصی که مد نظرتان است را انجام دهید. بعنوان نمونه، زمانیکه برنامه متوف است، اکتیویتی میبایست آبجکت ها و داده های حجیم مانند ارتباطات شبکه و دیتابیس را آزاد کند. زمانیکه فعالیت اکتویتی مجدداً از سر گرفته میشود، میتوانید دوباره منابع مورد نیازتان را بدست اورید و به ادامه کاری که قبلاً میکردید بپردازید. تمام این انتقال ها بین وضعیت های مختلف اکتیویتی بخشی از چرخه حیات اکتیویتی است.
به عنوان مثال،
1 – با دریافت یک تماس تلفنی یا سوئیچ به یک برنامه – برنامه شما خطا می دهد.
2 – باعث بالا رفتن مصرف منابع مهم می شود.
3 – از دست دادن کاربر.
4 – پرش از برنامه وقتی کاربر صفحه را به صورت عمودی می چرخاند.
این مطلب جزئیات چرخه فعالیت را توضیح می دهد که چه اتفاقی در هنگام اجرای آنها می افتد و چه چیزی باید در طول آنها اجرا شود.
مفاهیم چرخه حیاط اکتیویتی :
()onCreate – هنگامی که اکتیویتی برای اولین بار ایجاد می شود، فراخوانی می شود.
()onStart – هنگامی که اکتیویتی به کاربر نمایش داده می شود فراخوانی می گردد.
()onResume – هنگامی که اکتیویتی شروع به تعامل با کاربر می کند، فراخوانی می شود.
()onPause – هنگامی که اکتیویتی کنونی موقتا نگه داشته می شود و اکتیویتی قبلی در حال شروع به کار شدن است، فراخوانی می شود.
()onStop – هنگامی که دیگر اکتیویتی به کاربر نمایش داده نمی شود، فراخوانی می شود.
()onDestroy – قبل از اینکه اکتیویتی کاملا از بین برود، توسط سیستم فراخوانی می شود.
()onRestart – هنگامی که اکتیویتی پس از توقف دوباره شروع به کار می کند، فراخوانی می شود.
خوب همون طور که در تصویر بالا دید زمان های مختلفی از یک اکتیویتی نشان داده شده که خانه اندروید مهمترین بخش ها رو خدمت شما معرفی می کنه وقتی کاربر وارد یک اکتیویتی می شود برای اولین بار برنامه اندرویدی ما وارد متد onCreate میشه و کدهای موجود در اون رو Run می کنه خوب حالا اگه کاربر برروی یک دکمه کلیک کنه و وارد یه اکتیویتی جدید بشه اکتیویتی قبلی وارد onPause میشه و اگه کاربر مدت زمان زیادی رو وارد اکتیویتی قبلیه نشه اکتیویتی وارد onStop و بعد مدتی هم وارد onDestroy میشه .
خوب حالا اگه اکتیویتی داخل onPause باشه و کاربر به اکتیویتی برگرده کدهای موجود در onResume اجرا میشه ولی اگه اکتیویتی بسته شده باشه کدهای داخل onCreate از نو شروع میشه .
Lifecycle callbacks:
متد () onCreate :
()onSaveInstanceState متدی است که شما می توانید با آن وضعیت فعلی اکتیویتی تان را ذخیره کنید. سیستم این متد را قبل از اینکه اکتیویتی نابود شود و به شیئ Bundle فرستاده شود، فرا میخواند. Bundle جایی است که شما می توانید اطلاعات مربوط به وضعیت اکتیویتی تان را مانند نام ها با استفاده از متد ()putString، ذخیره کنید. حال اگر سیستم اکتیویتی شما را نابود کند و کاربر به اکتیویتی برگردد، سیستم Bundle را به ()onCreate ارسال میکند و بنابراین با این روششما می توانید وضعیت قبلی اکتیویتی تان را که با استفاده از متد ()onSaveInstanceState ذخیره کرده بودید، بازیابی کنید. اگر اطلاعاتی برای بازیابی موجود نباشد، مقدار Bundleی که به ()onCreate ارسال شده است، تهی (null) خواهد بود.
TextView mTextView;
// some transient state for the activity instance
String mGameState;
@Override
public void onCreate(Bundle savedInstanceState) {
// call the super class onCreate to complete the creation of activity like
// the view hierarchy
super.onCreate(savedInstanceState);
// recovering the instance state
if (savedInstanceState != null) {
mGameState = savedInstanceState.getString(GAME_STATE_KEY);
}
// set the user interface layout for this Activity
// the layout file is defined in the project res/layout/main_activity.xml file
setContentView(R.layout.main_activity);
// initialize member TextView so we can manipulate it later
mTextView = (TextView) findViewById(R.id.text_view);
}
// This callback is called only when there is a saved instance previously saved using
// onSaveInstanceState(). We restore some state in onCreate() while we can optionally restore
// other state here, possibly usable after onStart() has completed.
// The savedInstanceState Bundle is same as the one used in onCreate().
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
mTextView.setText(savedInstanceState.getString(TEXT_VIEW_KEY));
}
// invoked when the activity may be temporarily destroyed, save the instance state here
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putString(GAME_STATE_KEY, mGameState);
outState.putString(TEXT_VIEW_KEY, mTextView.getText());
// call superclass to save any view hierarchy
super.onSaveInstanceState(outState);
}
متد () onStart :
درست قبل از اینکه اکتیویتی برای کاربر قابل مشاهده باشد، فراخوانی می شود. اگر اکتیویتی به جلو یا پشت دیگر اکتیویتی ها برود، باید متدهای ()onResume و ()onStop بعد از آن اجرا شود.
متد () onResume :
این متد دقیقاً قبل از اینکه اکتیویتی بخواهد با کاربر تعاملش را آغاز کند، فراخوانی میشود. در این زمان، اکتیویتی در بالاترین نقطه انباره (Stack) قرار دارد و میتواند با کاربر در تعامل باشد. همیشه بعد از آن متد ()onPause باید اجرا شود.
@Override
public void onResume() {
super.onResume(); // Always call the superclass method first
// Get the Camera instance as the activity achieves full user focus
if (mCamera == null) {
initializeCamera(); // Local method to handle camera init
}
}
متد () onPause :
این متد زمانی فراخوانی میشود که اکتیویتی دیگری میخواهد اجرا شود (Resume). بطور معمول از این متد برای انجام کارهایی مانند ذخیره اطلاعاتی که هنوز ذخیره نشده اند، توقف انیمیشن و یا سایر کارهایی که CPU را بخودش درگیر کرده است، استفاده میشود. هر کاری که قرار است انجام شود باید بسیار سریع انجام شود زیرا تا زمانیکه وظیفه این متد انجام نشود، اکتیویتی بعدی اجرا نمیشود. متد بعد از این ()onResume است اگر اکتیویتی مجدداً بخواهد به نمایش درآید و یا ()onStop است اگر بخواهد از دید و دسترس کاربر پنهان شود.
@Override
public void onPause() {
super.onPause(); // Always call the superclass method first
// Release the Camera because we don't need it when paused
// and other activities might need to use it.
if (mCamera != null) {
mCamera.release();
mCamera = null;
}
}
متد () onStop :
زمانی اجرا میشود که اکتیویتی دیگر در دسترس کاربر نیست. این متد ممکن است بدلیل اینکه دارد نابود میشود، یا بدلیل اینکه اکتیویتی دیگری (چه اکتیویتی ای که قبلاً اجرا شده و الان در استک است و چه اکتیویتی جدید باشد) کارش را از سر گرفته است و دستور اینکار را داده باشد ، اجرا شود. متد بعد از آن ()onRestart است اگر اکتیویتی میخواهد برگردد تا در دسترس کاربر قرار گیرد و یا ()onDestroy است اگر اکتیویتی بخواهد نابود شود.
@Override
protected void onStop() {
// call the superclass method first
super.onStop();
// save the note's current draft, because the activity is stopping
// and we want to be sure the current note progress isn't lost.
ContentValues values = new ContentValues();
values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText());
values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle());
// do this update in background on an AsyncQueryHandler or equivalent
mAsyncQueryHandler.startUpdate (
mToken, // int token to correlate calls
null, // cookie, not used here
mUri, // The URI for the note to update.
values, // The map of column names and new values to apply to them.
null, // No SELECT criteria are used.
null // No WHERE columns are used.
);
}
متد () onDestroy :
این متد دقیقاً قبل از اینکه اکتیویتی بخواهد نابود شود، اجرا میشود. بعبارت دیگر این متد آخرین فراخوانی است که اکتیویتی دریافت خواهد کرد. این فراخوانی ممکن است به این دلیل باشد که اکتیویتی به پایان انجام وظیفه اش رسیده است (کسی متد ()finish را اجرا کرده است)، یا سیستم بمنظور در اختیار گرفتن فضای بیشتر نیاز دارد تا بعضی از اکتیویتی را نابود کند. متد ()isFinishing وجه تمایز دو سناریوی فوق است.
وضعیت Activity و خروج از حافظه
حرکت بین Activity ها:
شاید در طول اجرای برنامه چندین بار از یک اکتیویتی خارج و یا وارد آن شوید. به عنوان مثال، کاربر ممکن است دکمه برگشت دستگاه را لمس کند یا ممکن است از یک اکتیویتی به اکتیویتی دیگر برود. این بخش مباحثاتی را که شما باید بدانید و برای پیاده سازی Activity های مختلف استفاده کنید را پوشش می دهد. این موضوعات شامل شروع یک Activity از Activity دیگر، صرفه جویی در حالت Activity و بازگرداندن حالت Activity است.
شروع یک Activity
بسته به اینکه آیا Activity شما می خواهد نتیجه را از یک Activity جدید شروع کند و یا ممکن است Activity جدید را با استفاده از روش ()startActivity یا () startActivityForResult شروع کنید. در هر صورت، شما یک شی (Intent) Object را منتقل میکنید.
Intent در لغت به معنای انجام کار است. در اندروید هم تا حدود زیادی همین معنی را می رساند. به اینصورت که به واسطه intent به سیستم عامل اندروید اعلام می کنیم قصد انجام چه کاری را داریم و سیستم عامل چه کاری باید برای ما انجام دهد. به طور کلی اینتنت واسطی است مابین کامپوننت های مختلف (شامل Activity ها، Service ها، Broadcast Receiver ها) درون یک اپلیکیشن و یا مابین چند اپلیکیشن. کاربرد های متعددی برای اینتنت وجود دارد که شاید ساده ترین آن را بتوان انتقال بین دو Activity درون یک اپلیکیشن دانست. در Intent شما می توانید فعالیت و نوع آنرا مشخص کنید. یک Intent همچنین می تواند مقادیر کوچکی از داده ها را که توسط Activity هایی که آغاز شده است، حمل کند.
متد () startActivity :
وقتی که با اپلیکیشن کار می کنید شما اغلب نیاز دارید که به از یک اکتیویتی به اکیتیویتی دیگر بروید یا (launch) کنید.برای مثال کد زیر نشان می دهد که چگونه می توان با استفاده از intent یک اکتیویتی را صدا زد :
Intent intent = new Intent(this, SignInActivity.class);
startActivity(intent);
برنامه شما ممکن است بخواهد که یک (action) یا یک فعالیت را مانند ارسال ایمیل ی ارسال یک پیام (message) در این صورت میتوان intent را به صورت زیر تغییر داد :
Intent intent = new Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);
در بالا از EXTRA_EMAIL استفاده شده است یک آرایه رشته ای از آدرس های ایمیل می باشد که باید بصورت ایمیل فرستاده شود.
متد () startActivityForResult :
لزومی وجود ندارد که شروع activity های دیگر یکطرفه باشد. همچنین می توانید activity دیگری را شروع و نتیجه ای را دریافت کنید. برای دریافت نتیجه به جای startActivity() می توانید از () startActivityForResult, را فراخوانی کنید.
به عنوان مثال، برنامه شما می تواند یک برنامه دوربین را شروع و عکس گرفته شده را به عنوان یک نتیجه برگرداند. یا شما ممکن است برنامه دیگران را برای کاربری برای انتخاب مخاطب شروع کنید و جزئیات مخاطب را به عنوان نتیجه دریافت خواهید کرد.
البته activity ای که پاسخ می دهد باید برای برگرداندن یک نتیجه طراحی شود. هنگامی که این را انجام می دهد، این نتیجه به عنوان یک شی مقصد دیگر ارسال می شود. activity شما آن را در پاسخ onActivityResult() دریافت می کند.
هنگامی که activity کاربر با activity های پس از آن و مقدار بازگشتی به اتمام می رسد، سیستم تابع onActivityResult() activity شما را فراخوانی می کند. این تابع شامل سه آرگومان است:
1 کد درخواستی که شما به () startActivityForResult فرستاده اید .
2 کد نتیجه توسط activity دوم مشخص شده است.اگر عملیات موفقیت آمیز باشد این RESULT_OK و RESULT_CANCELED اگر کاربر خارج شود یا عملیات ناموفق باشد.
3 مقصودی که حامل داده های نتیجه می باشد.
public class MyActivity extends Activity {
...
static final int PICK_CONTACT_REQUEST = 0;
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
// When the user center presses, let them pick a contact.
startActivityForResult(
new Intent(Intent.ACTION_PICK,
new Uri("content://contacts")),
PICK_CONTACT_REQUEST);
return true;
}
return false;
}
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
if (requestCode == PICK_CONTACT_REQUEST) {
if (resultCode == RESULT_OK) {
// A contact was picked. Here we will just display it
// to the user.
startActivity(new Intent(Intent.ACTION_VIEW, data));
}
}
}
}
وقتی یک activity توسط activity دیگر شروع می شود، هر دوی آنها داری چرخه حیات مربوط به خود هستند. اولین activity متوقف می شود و در حالت متوقف یا متوقف میگیرد و activity دیگری ایجاد می شود.
منظور از callback lifecycle مواقعی است که وقتی دو اکتیویتی در فعالیت یکسان هستند.یعنس وقتی که اکتیویتی A اکتیویتی B را صدا میزند:
1- متد () OnPause اجرا می شود برای اکتیویتی A.
2- متد onCreate(), onStart(), and onResume() در اکتیویتی B در حال اجرا هستند
3- اگر اکتیویتی A به مدت طولانی نمایش داده نشود متد onStop() اجرا می شود.
ذخیره و بازگرداندن State اکتیویتی
چند سناریو وجود دارد که در آن اکتیویتی شما به دلیل رفتار برنامه از بین می رود، مانند زمانی که کاربر بر روی دکمه Back کلیک کند یا فعالیت خود را با فراخوانی متد () finish تمام میکند. ممکن است وقتی از یک اکتیویتی خارج می شوید اطلاعات مربوز به آن اکتیویتی از بین برود مانند مقادیر ذخیره در متغیر ها یا اگر اکتیویتی در حالت متوقف باشد و در مدت زمان طولانی مورد استفاده قرار نگرفته باشد یا اکتیویتی پیشین به منابع بیشتری نیاز داشته باشد.
وقتی که یک activity متوقف شده است حالت activity باقی می ماند این فرضیه درست است چرا که شی activity هنوزدر حافظه نگهداری شده است وقتی متوفق می شود تمام اطلاعات وضعیت فعلی هنوز از بین نرفته است بنابراین متغیری که کاربر با استفاده از activity اعمال کرده است قابل بازیابی می باشد بنابرای وقتی activity دوباره ادامه پیدا کند این تغییرات هنوز آنجا هستند بنابراین وقتی که سیستم یک activity به منظور پوشش حافظه از بین ببرد شی activity از بین رفته بنابراین سیستم به راحتی نمی تواند حالت قبلی ذخیره شده را ادامه دهد .
() onSaveInstanceState متدی است که شما می توانید با آن وضعیت فعلی اکتیویتی تان را ذخیره کنید. سیستم این متد را قبل از اینکه اکتیویتی نابود شود و به شیئ Bundle فرستاده شود، فرا میخواند. Bundle جایی است که شما می توانید اطلاعات مربوط به وضعیت اکتیویتی تان را مانند نام ها با استفاده از متد () putString، ذخیره کنید. حال اگر سیستم اکتیویتی شما را نابود کند و کاربر به اکتیویتی برگردد، سیستم Bundle را به () onCreate ارسال میکند و بنابراین با این روششما می توانید وضعیت قبلی اکتیویتی تان را که با استفاده از متد () onSaveInstanceState ذخیره کرده بودید، بازیابی کنید. اگر اطلاعاتی برای بازیابی موجود نباشد، مقدار Bundleی که به () onCreate ارسال شده است، تهی (null) خواهد بود.
برای ذخیره اطلاعات مربوط به اکتیویتی خود، شما باید بر روی () SaveInstanceState باید به صورت زیر عمل کنید:
static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
...
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the user's current game state
savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
بازگرداندن State اکتیویتی:
وقتی اکتیویتی شما بعد نابود شدن دوباره ساخته و کار خود را شروع می کندشما می توانید تنظیماتی که دخیره کرده اید را بازیابی کنید با استفاده از متد onCreate() و onRestoreInstanceState()
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Always call the superclass first
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of members from saved state
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
} else {
// Probably initialize members with default values for a new instance
}
...
}
شما ممکن است به جای ()onCreate از متد ()onRestoreInstanceState استفاده کنید.متد ()onRestoreInstanceState فقط تنظیمات ذخیره شده را باز می گرداند.
public void onRestoreInstanceState(Bundle savedInstanceState) {
// Always call the superclass so it can restore the view hierarchy
super.onRestoreInstanceState(savedInstanceState);
// Restore state members from saved instance
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}
دیدگاهتان را بنویسید