07
مهدنیای توسعهی اپلیکیشنهای اندروید به طور مداوم در حال پیشرفت است و ابزارها و مفاهیم مختلفی برای ساخت اپلیکیشنهایی با تجربه کاربری بهتر ارائه میشود. یکی از این مفاهیم مهم Fragment است. اگر توسعهدهندهی اندروید باشید، احتمالاً بارها با واژهی Fragment مواجه شدهاید؛ اما واقعاً Fragment چیست؟ چرا به وجود آمد؟ چه مزایایی دارد و چه زمانی باید از آن استفاده کرد؟ در این مقاله قصد داریم به صورت جامع و دقیق به بررسی Fragment در اندروید بپردازیم.
Fragment در اندروید یک بخش قابلتکرار و قابلمدیریت از رابط کاربری یا منطق یک Activity است. میتوان آن را به عنوان یک زیر-Activity در نظر گرفت که میتواند به طور مستقل چرخهی حیات، رابط کاربری و رویدادهای خاص خود را داشته باشد.
در واقع، Fragmentها به توسعهدهنده این امکان را میدهند که رابط کاربری ماژولار و منعطفی طراحی کنند، به ویژه در دستگاههایی با اندازه صفحه مختلف مانند تبلتها و گوشیها.
پیش از ظهور Fragment، تمام منطق رابط کاربری و تعاملات آن درون Activityها پیادهسازی میشد. هر Activity به تنهایی مسئول نمایش یک صفحه از اپلیکیشن و مدیریت کامل آن بود. این رویکرد در اپلیکیشنهای ساده جوابگو بود، اما با پیچیدهتر شدن رابطهای کاربری، افزایش اندازهی صفحات نمایش در دستگاههای مختلف (مثل تبلتها و گوشیها با ابعاد گوناگون)، و رشد نیاز به طراحی اپلیکیشنهایی با رابط کاربری سازگار و واکنشگرا، توسعه اپلیکیشنهای اندرویدی به چالش کشیده شد.
برای مثال، فرض کنید در یک اپلیکیشن خبری، شما باید هم لیست خبرها را نمایش دهید و هم جزئیات هر خبر را. در گوشی، این دو بخش معمولاً در صفحات جداگانه قرار میگیرند، اما در تبلت میتوان آنها را در یک صفحه، در کنار هم نشان داد. اگر بخواهید با روش کلاسیک (یعنی فقط با Activity) این کار را انجام دهید، مجبورید بخش زیادی از کد را تکرار کنید یا ساختاری پیچیده پیادهسازی کنید که نگهداری آن دشوار خواهد بود.
برای حل این چالشها، گوگل در نسخهی Android 3.0 (Honeycomb) که مخصوص تبلتها بود، مفهومی به نام Fragment را معرفی کرد. هدف اصلی این ویژگی، افزایش انعطافپذیری در طراحی رابطهای کاربری و بهبود ساختار کدها بود. برخی از دلایل اصلی و اهداف معرفی Fragment عبارتاند از:
Fragment به توسعهدهندگان این امکان را میدهد که بخشهایی از رابط کاربری یا منطق برنامه را به صورت ماژولهای مستقل توسعه دهند. این ماژولها میتوانند به صورت جداگانه طراحی، تست و بازاستفاده شوند. این یعنی:
کاهش وابستگی بین اجزای مختلف برنامه
افزایش خوانایی و قابلنگهداری بودن کد
سادهتر شدن توسعهی تدریجی و افزایشی
با استفاده از Fragment، توسعهدهندگان میتوانند به راحتی رابطهای کاربری منعطف و سازگار با انواع دستگاهها طراحی کنند. مثلاً:
در دستگاههای کوچک (مانند گوشی)، تنها یک Fragment در یک زمان نمایش داده میشود.
در دستگاههای بزرگتر (مانند تبلت)، میتوان چندین Fragment را به طور همزمان در یک Activity قرار داد.
این قابلیت باعث شده طراحی رابط کاربری یکپارچه برای چند اندازه صفحهنمایش بسیار سادهتر و بهینهتر شود.
یکی از مزایای مهم Fragment، قابلیت استفادهی مجدد از منطق و رابط کاربری آن است. برای مثال، اگر شما یک Fragment طراحی کردهاید که اطلاعات پروفایل کاربر را نمایش میدهد، میتوانید از همین Fragment در چند Activity مختلف (مثلاً در صفحه تنظیمات، یا در داشبورد اصلی) استفاده کنید بدون اینکه نیازی به کپیکردن کدها یا تکرار طراحی داشته باشید.
Fragmentها همچنین به شکل مؤثری با سیستم ناوبری اندروید یکپارچه شدهاند. در نسخههای جدید اندروید، بهخصوص با معرفی Jetpack Navigation Component، ناوبری بین Fragmentها سادهتر و قابلکنترلتر از قبل شده است. دیگر نیازی به تعریف تعداد زیادی Activity برای هر بخش از اپلیکیشن نیست و میتوان تنها با چند Activity اصلی و ترکیبی از Fragmentها، ناوبری روان و ساختارمند داشت.
برای ساخت یک Fragment، ابتدا یک کلاس جدید ایجاد میکنید که از کلاس پایهی Fragment ارثبری کند. در داخل این کلاس، تابعی به نام onCreateView
را تعریف میکنید تا هنگام اجرا، فایل XML مربوط به رابط کاربری این Fragment را بارگذاری کند. فایل XML موردنظر معمولاً در پوشه res/layout
قرار دارد و میتواند شامل هر نوع ترکیب رابط کاربری (مانند TextView، RecyclerView، دکمه و …) باشد.
اگر بخواهید Fragment بهصورت پیشفرض هنگام اجرای Activity نمایش داده شود، میتوانید آن را مستقیم در فایل XML رابط Activity وارد کنید. در این حالت، تنها کافی است نام کامل کلاس Fragment را مشخص کرده و طول و عرض نمای آن را تعیین کنید. این روش برای زمانی مناسب است که میدانید Fragment همیشه باید نمایش داده شود و حالتهای پویا یا تغییرات در زمان اجرا نیاز نیست.
برای ایجاد رابطهای پویا، معمولاً Fragment را در زمان اجرا به Activity اضافه میکنند. در این حالت، ابتدا مرجعی به کنترلکننده Fragmentها در Activity میگیرید، سپس یک تراکنش (فرآیند تغییر) آغاز میکنید، و در آن مشخص میکنید که Fragment موردنظر در کدام بخش از رابط (مثلاً درون یک قاب یا Layout خاص) جایگذاری شود. در پایان نیز تراکنش را نهایی کرده و تغییرات اعمال میشوند. این روش زمانی کاربرد دارد که، برای مثال، کاربر با فشردن یک دکمه بخواهد وارد بخش جدیدی از اپلیکیشن شود.
در نسخههای جدید اندروید، بهجای استفاده از تگ قدیمی fragment
در XML، توصیه میشود از View خاصی به نام FragmentContainerView استفاده شود. این View مدرنتر است، هماهنگی بهتری با کتابخانههای Jetpack دارد، و برای استفاده با سیستم ناوبری جدید اندروید طراحی شده است. شما میتوانید آن را در فایل XML تعریف کرده و بعداً در زمان اجرا، Fragment موردنظر را درون آن جایگزین کنید.
چرخه حیات Fragment شبیه به Activity است ولی کمی پیچیدهتر به دلیل وابستگی به Activity والد. برخی از متدهای مهم عبارتاند از:
onAttach()
onCreate()
onCreateView()
onActivityCreated()
onStart()
onResume()
onPause()
onStop()
onDestroyView()
onDestroy()
onDetach()
طراحی رابطهای چندبخشی:
مثلاً در تبلت، یک صفحه میتواند دو Fragment داشته باشد: لیست سمت چپ و جزئیات سمت راست.
استفاده مجدد از منطق یا UI:
Fragment میتواند در چند Activity مختلف بهکار رود.
ساختن UI پویا:
میتوان در زمان اجرا، Fragment جدید اضافه یا جایگزین کرد.
مدیریت بهتر Navigation:
با استفاده از Fragmentها، مدیریت ناوبری (Navigation) سادهتر میشود، بهویژه در ترکیب با Jetpack Navigation.
ماژولار بودن: میتوان قطعات مختلف اپلیکیشن را در قالب Fragment توسعه داد و به راحتی ترکیب کرد.
قابلیت استفاده مجدد: امکان استفاده از یک Fragment در چند صفحه وجود دارد.
پشتیبانی بهتر از Multi-pane UI: در دستگاههایی با صفحه بزرگتر.
ناوبری سادهتر در معماریهای مدرن مانند MVVM با استفاده از Jetpack Navigation.
مدیریت بهتر حافظه: Fragmentها سبکتر از Activity هستند.
پیچیدگی بیشتر در مدیریت چرخه حیات.
نیاز به هماهنگی زیاد با Activity میزبان.
احتمال بروز خطاهای ناخواسته هنگام جابجایی بین Fragmentها.
مدیریت سختتر در مقایسه با View ساده برای اپلیکیشنهای کوچک.
در مقایسه بین Activity و Fragment در اندروید، تفاوتهای مهمی وجود دارد که در ادامه به آنها به صورت نکتهوار اشاره میکنیم:
میزان استقلال:
Activityها کاملاً مستقل عمل میکنند و میتوانند به تنهایی اجرا شوند. در مقابل، Fragmentها همیشه به یک Activity نیاز دارند و بدون آن قابل استفاده نیستند.
چرخه حیات (Lifecycle):
چرخه حیات Activity سادهتر و واضحتر است. اما Fragmentها چرخهی حیات پیچیدهتری دارند چون علاوه بر Lifecycle خود، با چرخهی Activity میزبان نیز درگیر هستند.
قابلیت استفاده مجدد (Reusability):
Fragmentها بهخاطر ساختار ماژولار، بیشتر قابل استفاده مجدد هستند. میتوان یک Fragment را در چند Activity یا حالت نمایش مختلف استفاده کرد، اما Activityها چنین انعطافی ندارند.
پشتیبانی از ناوبری (Navigation):
Activityها بهتنهایی از ناوبری پشتیبانی میکنند، اما ناوبری در ترکیب Fragment با Activity به همراه Jetpack Navigation بسیار قدرتمندتر و مدرنتر پیادهسازی میشود.
پیچیدگی توسعه:
توسعه و مدیریت Activityها نسبتاً سادهتر است. در حالیکه Fragmentها با وجود انعطافپذیری بالا، به دلیل ساختار پیچیدهتر و نیاز به هماهنگی با Activity میزبان، توسعهی دشوارتری دارند.
در اندروید، برای مدیریت Fragmentها نیاز به FragmentManager
داریم. اما این کلاس در دو نسخه مختلف ارائه شده:
getFragmentManager()
در نسخهی قدیمیتر اندروید استفاده میشود و مربوط به API پایه است.
getSupportFragmentManager()
مربوط به کتابخانهی پشتیبانی (Support Library) است که با نسخههای پایینتر اندروید نیز سازگار است و ویژگیهای بیشتری ارائه میدهد.
در توسعههای مدرن اندروید (با استفاده از AndroidX)، توصیه اکید این است که همیشه از getSupportFragmentManager()
استفاده کنید، چرا که:
از Fragmentهای جدید AndroidX پشتیبانی میکند.
با معماری مدرن اندروید (Jetpack Components) سازگاری دارد.
مدیریت دقیقتر و بهتری در مورد Lifecycle و Navigation دارد.
بنابراین اگر در حال توسعه با AppCompatActivity
یا FragmentActivity
هستید، بهتر است همیشه getSupportFragmentManager()
را انتخاب کنید.
Fragmentها نباید به صورت مستقیم با Activity میزبان یا دیگر Fragmentها در ارتباط باشند، زیرا این کار باعث ایجاد وابستگی و پیچیدگی بیش از حد میشود. برای حل این مشکل، دو روش حرفهای و پیشنهادی وجود دارد:
در این روش، یک Interface تعریف میشود که Activity آن را پیادهسازی میکند. سپس Fragment میتواند این Interface را فراخوانی کند بدون آنکه چیزی از Activity بداند. این الگو مناسب زمانی است که Fragment نیاز دارد یک عملیات را در Activity اجرا کند (مثلاً اطلاع دادن کلیک روی یک آیتم).
در معماری MVVM و با استفاده از ViewModel، میتوان یک ViewModel مشترک بین Activity و Fragment یا بین چند Fragment تعریف کرد. این ViewModel وظیفه انتقال دادهها و مدیریت وضعیت مشترک را بر عهده دارد. این روش بسیار تمیزتر و قابل نگهداریتر است و برای اپهای مدرن توصیه میشود.
وقتی Fragment جدیدی را به یک Activity اضافه میکنید (مثلاً با replace()
یا add()
)، اگر میخواهید امکان بازگشت (Back) به Fragment قبلی وجود داشته باشد، باید Fragment جدید را به Back Stack اضافه کنید. در غیر این صورت، با زدن دکمه بازگشت (Back)، برنامه ممکن است بسته شود یا رفتار نامطلوبی داشته باشدتوجه داشته باشید که مدیریت صحیح back stack در طراحی تجربه کاربری (UX) بسیار مهم است.
popBackStack()
استفاده کنیدبرای حذف یک Fragment از back stack، نباید از روشهایی مانند remove()
به تنهایی استفاده کنید، چون ممکن است ترتیب یا وضعیت back stack را بههم بزند. در عوض، از تابع استاندارد popBackStack()
استفاده کنید، که Fragment فعلی را از پشته خارج میکند و به Fragment قبلی بازمیگردد.
این روش:
به صورت خودکار Fragment را از UI حذف میکند
وضعیت back stack را مدیریت میکند
با Navigation به شکل درست هماهنگ است
همچنین میتوانید پارامترهایی به popBackStack()
بدهید تا تا یک نقطه خاص از stack را پاک کند.
در گذشته معمول بود برای جایگذاری Fragmentها در layout از FrameLayout
استفاده شود. اما با معرفی FragmentContainerView
در AndroidX، گوگل توصیه کرده است که در پروژههای جدید از این View استفاده شود.
مزایای FragmentContainerView:
هماهنگی بهتر با Lifecycle جدید Fragmentها
پشتیبانی کامل از انیمیشنها و Transitionها
عملکرد بهتر هنگام استفاده از Navigation Component
در XML بهجای استفاده از FrameLayout برای جایگذاری Fragment میتوانید از:
با اینکه Fragment همچنان بخش حیاتی و پرکاربردی از توسعه اپلیکیشنهای اندروید است، اما با ظهور ابزارها و معماریهای نوین، مسیر توسعه به سمت روشهایی مدرنتر تغییر کرده است. یکی از برجستهترین این تغییرات، ورود Jetpack Compose به دنیای طراحی رابط کاربری اندروید است؛ Compose رویکردی کاملاً متفاوت با XML سنتی دارد و بهصورت declarative (اعلانی) طراحی شده است. در Compose، دیگر نیازی به تعریف XML جداگانه و مدیریت دستی Viewها نیست، و همین موضوع باعث شده بسیاری از توسعهدهندگان جدید به سمت حذف کامل Fragmentها بروند و UI خود را صرفاً با استفاده از Composableها پیادهسازی کنند.
با این حال، در دنیای واقعی توسعه اندروید، هنوز هم بسیاری از اپلیکیشنها — بهخصوص پروژههای بزرگ، سازمانی یا قدیمیتر — بر پایهی ساختار کلاسیک Activity و Fragment توسعه یافتهاند. حتی در پروژههای مدرن که از Jetpack Compose استفاده میکنند، در بسیاری موارد برای استفاده از قابلیتهایی مانند Navigation یا Lifecycle، یا هنگام مهاجرت تدریجی از کدهای قدیمی، هنوز نیاز به تعامل با Fragment وجود دارد.
به همین دلیل است که Fragment هنوز هم یک مهارت کلیدی و کاربردی برای هر توسعهدهنده اندروید بهشمار میرود. تسلط بر Fragment نهتنها به شما کمک میکند در پروژههای متنوعتر کار کنید، بلکه توانایی ترکیب مؤثر معماریهای جدید و قدیم را در اختیار شما میگذارد — قابلیتی که در بازار کار و توسعه اپهای واقعی بسیار ارزشمند است.
Fragment در اندروید برای طراحی رابط کاربری ماژولار و قابلتطبیق است. با استفاده درست از آن، میتوان اپلیکیشنهایی ساخت که هم در گوشی و هم در تبلت بهخوبی کار میکنند. البته کار با Fragment نیازمند درک درست از چرخه حیات، ارتباط بین اجزا و مدیریت ناوبری است. در نهایت، انتخاب بین استفاده از Activity یا Fragment به اندازه پروژه، ساختار اپلیکیشن و نیازهای شما بستگی دارد.
بیشتر بخوانید :”مزایای SvelteJS در توسعه وب“
در خبرنامه ما مشترک شوید و آخرین اخبار و به روزرسانی های را در صندوق ورودی خود مستقیماً دریافت کنید.
دیدگاه بگذارید