کتابخانه Dynamic Navigator عملکرد مولفه Jetpack Navigation را برای کار با مقاصدی که در ماژول های ویژگی تعریف شده اند گسترش می دهد. این کتابخانه همچنین نصب یکپارچه ماژول های ویژگی درخواستی را هنگام حرکت به این مقاصد فراهم می کند.
راه اندازی
برای پشتیبانی از ماژول های ویژگی، از وابستگی های زیر در فایل build.gradle
ماژول برنامه خود استفاده کنید:
شیار
dependencies { def nav_version = "2.8.4" api "androidx.navigation:navigation-fragment-ktx:$nav_version" api "androidx.navigation:navigation-ui-ktx:$nav_version" api "androidx.navigation:navigation-dynamic-features-fragment:$nav_version" }
کاتلین
dependencies { val nav_version = "2.8.4" api("androidx.navigation:navigation-fragment-ktx:$nav_version") api("androidx.navigation:navigation-ui-ktx:$nav_version") api("androidx.navigation:navigation-dynamic-features-fragment:$nav_version") }
توجه داشته باشید که وابستگیهای ناوبری دیگر باید از تنظیمات api استفاده کنند تا برای ماژولهای ویژگی شما در دسترس باشند.
استفاده اساسی
برای پشتیبانی از ماژول های ویژگی، ابتدا همه نمونه های NavHostFragment
در برنامه خود را به androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment
تغییر دهید:
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.dynamicfeatures.fragment.DynamicNavHostFragment"
app:navGraph="@navigation/nav_graph"
... />
سپس، یک ویژگی app:moduleName
به هر مقصد <activity>
، <fragment>
، یا <navigation>
در نمودارهای ناوبری ماژول com.android.dynamic-feature
که با DynamicNavHostFragment
مرتبط هستند، اضافه کنید. این ویژگی به کتابخانه Dynamic Navigator می گوید که مقصد متعلق به یک ماژول ویژگی با نامی است که شما مشخص می کنید.
<fragment
app:moduleName="myDynamicFeature"
android:id="@+id/featureFragment"
android:name="com.google.android.samples.feature.FeatureFragment"
... />
هنگامی که به یکی از این مقاصد حرکت می کنید، کتابخانه Dynamic Navigator ابتدا بررسی می کند که آیا ماژول ویژگی نصب شده است یا خیر. اگر ماژول ویژگی از قبل وجود داشته باشد، برنامه شما همانطور که انتظار می رود به مقصد حرکت می کند. اگر ماژول موجود نباشد، برنامه شما هنگام نصب ماژول، مقصد قطعه پیشرفت متوسط را نشان می دهد. اجرای پیشفرض قطعه پیشرفت یک رابط کاربری پایه با نوار پیشرفت را نشان میدهد و هرگونه خطای نصب را کنترل میکند.
برای سفارشی کردن این رابط کاربری، یا برای کنترل دستی پیشرفت نصب از داخل صفحه برنامه خود، بخش سفارشی کردن پیشرفت و نظارت بر وضعیت درخواست را در این مبحث ببینید.
مقصدهایی که app:moduleName
مشخص نمی کنند بدون تغییر به کار خود ادامه می دهند و طوری رفتار می کنند که گویی برنامه شما از NavHostFragment
معمولی استفاده می کند.
قطعه پیشرفت را سفارشی کنید
میتوانید اجرای قطعه پیشرفت را برای هر نمودار ناوبری با تنظیم app:progressDestination
روی شناسه مقصدی که میخواهید برای مدیریت پیشرفت نصب استفاده کنید، لغو کنید. مقصد پیشرفت سفارشی شما باید یک Fragment
باشد که از AbstractProgressFragment
مشتق شده باشد. شما باید روشهای انتزاعی را برای اعلانهای مربوط به پیشرفت نصب، خطاها و سایر رویدادها لغو کنید. سپس می توانید پیشرفت نصب را در UI مورد نظر خود نشان دهید.
کلاس DefaultProgressFragment
پیاده سازی پیش فرض از این API برای نشان دادن پیشرفت نصب استفاده می کند.
وضعیت درخواست را نظارت کنید
کتابخانه Dynamic Navigator شما را قادر میسازد تا یک جریان UX مشابه آنچه در بهترین شیوههای UX برای تحویل درخواستی وجود دارد ، پیادهسازی کنید، که در آن کاربر در حالی که منتظر پایان نصب است، در متن صفحه قبلی میماند. این به این معنی است که شما اصلا نیازی به نمایش یک رابط کاربری متوسط یا قطعه پیشرفت ندارید.
در این سناریو شما مسئول نظارت و مدیریت تمامی حالت های نصب، تغییرات پیشرفت، خطاها و غیره هستید.
برای شروع این جریان ناوبری غیر مسدود کننده، یک شی DynamicExtras
که حاوی DynamicInstallMonitor
است را به NavController.navigate()
ارسال کنید، همانطور که در مثال زیر نشان داده شده است:
کاتلین
val navController = ... val installMonitor = DynamicInstallMonitor() navController.navigate( destinationId, null, null, DynamicExtras(installMonitor) )
جاوا
NavController navController = ... DynamicInstallMonitor installMonitor = new DynamicInstallMonitor(); navController.navigate( destinationId, null, null, new DynamicExtras(installMonitor); )
بلافاصله پس از فراخوانی navigate()
باید مقدار installMonitor.isInstallRequired
را بررسی کنید تا ببینید آیا تلاش برای ناوبری منجر به نصب ماژول ویژگی شده است یا خیر.
- اگر مقدار
false
است، به یک مقصد عادی می روید و نیازی به انجام کار دیگری ندارید. اگر مقدار
true
است، باید شروع به مشاهده شیLiveData
کنید که اکنون درinstallMonitor.status
است. این شیLiveData
بهروزرسانیهایSplitInstallSessionState
را از کتابخانه Play Core منتشر میکند. این بهروزرسانیها حاوی رویدادهای پیشرفت نصب هستند که میتوانید از آنها برای بهروزرسانی رابط کاربری استفاده کنید. به یاد داشته باشید که تمام وضعیت های مربوطه را همانطور که در راهنمای Play Core ذکر شده است، از جمله درخواست تأیید کاربر در صورت لزوم انجام دهید.کاتلین
val navController = ... val installMonitor = DynamicInstallMonitor() navController.navigate( destinationId, null, null, DynamicExtras(installMonitor) ) if (installMonitor.isInstallRequired) { installMonitor.status.observe(this, object : Observer<SplitInstallSessionState> { override fun onChanged(sessionState: SplitInstallSessionState) { when (sessionState.status()) { SplitInstallSessionStatus.INSTALLED -> { // Call navigate again here or after user taps again in the UI: // navController.navigate(destinationId, destinationArgs, null, null) } SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION -> { SplitInstallManager.startConfirmationDialogForResult(...) } // Handle all remaining states: SplitInstallSessionStatus.FAILED -> {} SplitInstallSessionStatus.CANCELED -> {} } if (sessionState.hasTerminalStatus()) { installMonitor.status.removeObserver(this); } } }); }
جاوا
NavController navController = ... DynamicInstallMonitor installMonitor = new DynamicInstallMonitor(); navController.navigate( destinationId, null, null, new DynamicExtras(installMonitor); ) if (installMonitor.isInstallRequired()) { installMonitor.getStatus().observe(this, new Observer<SplitInstallSessionState>() { @Override public void onChanged(SplitInstallSessionState sessionState) { switch (sessionState.status()) { case SplitInstallSessionStatus.INSTALLED: // Call navigate again here or after user taps again in the UI: // navController.navigate(mDestinationId, mDestinationArgs, null, null); break; case SplitInstallSessionStatus.REQUIRES_USER_CONFIRMATION: SplitInstallManager.startConfirmationDialogForResult(...) break; // Handle all remaining states: case SplitInstallSessionStatus.FAILED: break; case SplitInstallSessionStatus.CANCELED: break; } if (sessionState.hasTerminalStatus()) { installMonitor.getStatus().removeObserver(this); } } }); }
هنگامی که نصب به پایان می رسد، شی LiveData
وضعیت SplitInstallSessionStatus.INSTALLED
را منتشر می کند. سپس باید NavController.navigate()
را دوباره فراخوانی کنید. از آنجایی که ماژول اکنون نصب شده است، تماس اکنون با موفقیت انجام می شود و برنامه همانطور که انتظار می رود به مقصد حرکت می کند.
پس از رسیدن به یک حالت ترمینال، مانند زمانی که نصب کامل شد یا زمانی که نصب با شکست مواجه شد، برای جلوگیری از نشت حافظه، باید ناظر LiveData
خود را حذف کنید. با استفاده از SplitInstallSessionStatus.hasTerminalStatus()
می توانید بررسی کنید که آیا وضعیت وضعیت ترمینال را نشان می دهد.
AbstractProgressFragment
را برای اجرای نمونه ای از این مشاهدهگر ببینید.
شامل نمودارها
کتابخانه Dynamic Navigator شامل نمودارهایی است که در ماژول های ویژگی تعریف شده اند. برای گنجاندن نموداری که در یک ماژول ویژگی تعریف شده است، موارد زیر را انجام دهید:
همانطور که در مثال زیر نشان داده شده است، به جای <include
<include/>
<include-dynamic/>
استفاده کنید:<include-dynamic android:id="@+id/includedGraph" app:moduleName="includedgraphfeature" app:graphResName="included_feature_nav" app:graphPackage="com.google.android.samples.dynamic_navigator.included_graph_feature" />
در داخل
<include-dynamic ... />
، باید ویژگی های زیر را مشخص کنید:-
app:graphResName
: نام فایل منبع گراف ناوبری. نام از نام فایل نمودار گرفته شده است. به عنوان مثال، اگر نمودار درres/navigation/nav_graph.xml
باشد، نام منبعnav_graph
است. -
android:id
- شناسه مقصد گراف. کتابخانه Dynamic Navigator هر مقدارandroid:id
که در عنصر ریشه گراف موجود است نادیده می گیرد. -
app:moduleName
: نام بسته ماژول.
-
از graphPackage صحیح استفاده کنید
مهم است که app:graphPackage
به درستی دریافت کنید، زیرا در غیر این صورت، مؤلفه Navigation قادر نخواهد بود navGraph
مشخص شده را از ماژول ویژگی اضافه کند.
نام بسته یک ماژول ویژگی پویا با الحاق نام ماژول به applicationId
ماژول برنامه پایه ساخته می شود. بنابراین اگر ماژول برنامه پایه دارای یک applicationId
از com.example.dynamicfeatureapp
باشد و ماژول ویژگی پویا DynamicFeatureModule
نام داشته باشد، نام بسته ماژول پویا com.example.dynamicfeatureapp.DynamicFeatureModule
خواهد بود. این نام بسته به حروف کوچک و بزرگ حساس است.
اگر شک دارید، میتوانید نام بسته ماژول ویژگی را با بررسی AndroidManifest.xml
ایجاد شده تأیید کنید. پس از ساخت پروژه به <DynamicFeatureModule>/build/intermediates/merged_manifest/debug/AndroidManifest.xml
بروید، که باید چیزی شبیه به این باشد:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:dist="http://schemas.android.com/apk/distribution" featureSplit="DynamicFeatureModule" package="com.example.dynamicfeatureapp" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30" /> <dist:module dist:instant="false" dist:title="@string/title_dynamicfeaturemodule" > <dist:delivery> <dist:install-time /> </dist:delivery> <dist:fusing dist:include="true" /> </dist:module> <application /> </manifest>
مقدار featureSplit
باید با نام ماژول ویژگی پویا مطابقت داشته باشد و بسته با applicationId
ماژول برنامه پایه مطابقت دارد. app:graphPackage
ترکیبی از این موارد است: com.example.dynamicfeatureapp.DynamicFeatureModule
.
پیمایش به یک نمودار ناوبری شامل پویا
فقط می توان به startDestination
یک نمودار ناوبری include-dynamic
پیمایش کرد. ماژول پویا مسئول نمودار ناوبری خود است و برنامه پایه هیچ اطلاعی از آن ندارد.
مکانیزم شامل پویا ماژول برنامه پایه را قادر می سازد که یک نمودار ناوبری تودرتو که در ماژول پویا تعریف شده است را شامل شود. این نمودار ناوبری تودرتو مانند هر نمودار ناوبری تو در تو عمل می کند. نمودار ناوبری ریشه (یعنی والد گراف تودرتو) فقط می تواند خود نمودار ناوبری تودرتو را به عنوان مقصد تعریف کند و نه فرزندان آن را. بنابراین، startDestination
زمانی استفاده می شود که گراف ناوبری شامل-دینامیک مقصد باشد.
محدودیت ها
- نمودارهایی که به صورت پویا درج شده اند در حال حاضر از پیوندهای عمیق پشتیبانی نمی کنند.
- نمودارهای تو در تو با بارگذاری پویا (یعنی عنصر
<navigation>
باapp:moduleName
) در حال حاضر از پیوندهای عمیق پشتیبانی نمی کنند.