يمكنك استخدام مكتباتك المفضّلة في ميزة "الإنشاء". يوضِّح هذا القسم كيفية دمج بعض المكتبات الأكثر فائدة.
النشاط
لاستخدام Compose في نشاط، يجب استخدام
ComponentActivity
،
وهي فئة فرعية من Activity
تقدّم مكوّنات LifecycleOwner
و
المناسبة لCompose. وتوفّر أيضًا واجهات برمجة تطبيقات إضافية تفصل رمزك عن التداخل مع الطرق في فئة النشاط.
تُعرِض Activity Compose
واجهات برمجة التطبيقات هذه للعناصر القابلة للتجميع، ما يجعل إلغاء طُرق خارج العناصر القابلة للتجميع أو استرداد مثيل Activity
صريح غير مطلوب.
بالإضافة إلى ذلك، تضمن واجهات برمجة التطبيقات هذه أن يتمّ إعدادها مرّة واحدة فقط، وأنّها تبقى صالحة بعد
إعادة التركيب، وأنّها يتمّ تنظيفها بشكل صحيح في حال إزالة العنصر القابل للتجميع من
التركيب.
نتيجة النشاط
تتيح لك واجهة برمجة التطبيقات
rememberLauncherForActivityResult()
الحصول على نتيجة من نشاط
في العنصر القابل للتجميع:
@Composable fun GetContentExample() { var imageUri by remember { mutableStateOf<Uri?>(null) } val launcher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? -> imageUri = uri } Column { Button(onClick = { launcher.launch("image/*") }) { Text(text = "Load Image") } Image( painter = rememberAsyncImagePainter(imageUri), contentDescription = "My Image" ) } }
يوضّح هذا المثال GetContent()
عقدًا بسيطًا. يؤدي النقر على الزر إلى بدء الطلب. يتمّ استدعاء دالة lambda اللاحقة لملف rememberLauncherForActivityResult()
بعد أن يختار المستخدِم صورة ويعود إلى نشاط الإطلاق.
يؤدي ذلك إلى تحميل الصورة المحدّدة باستخدام rememberImagePainter()
دالة
في Coil.
يمكن استخدام أي فئة فرعية من
ActivityResultContract
كوسيطة أولى لدالة
rememberLauncherForActivityResult()
.
وهذا يعني أنّه يمكنك استخدام هذه الطريقة لطلب المحتوى من إطار العمل
وفي أنماط شائعة أخرى. يمكنك أيضًا إنشاء
عقود مخصّصة واستخدامها مع
هذه التقنية.
طلب أذونات وقت التشغيل
يمكن استخدام Activity Result API وrememberLauncherForActivityResult()
الموضّحين أعلاه للقيام بما يلي:
طلب أذونات وقت التشغيل
باستخدام RequestPermission
عقد إذن واحد أو RequestMultiplePermissions
عقد لأذونات متعددة.
يمكن أيضًا استخدام مكتبة أذونات المصاحب كطبقة فوق واجهات برمجة التطبيقات هذه لربط الحالة الممنوحة الحالية ل الأذونات بالحالة التي يمكن لواجهة مستخدِم "الإنشاء" استخدامها.
التعامل مع زر الرجوع في النظام
لتوفير ميزة التنقل للخلف المخصّصة
وتجاوز السلوك التلقائي لزر الرجوع في النظام من داخل
العنصر القابل للتجميع، يمكن للعنصر القابل للتجميع استخدام
BackHandler
لاعتراض هذا الحدث:
var backHandlingEnabled by remember { mutableStateOf(true) } BackHandler(backHandlingEnabled) { // Handle back press }
تتحكّم الوسيطة الأولى في ما إذا كان
BackHandler
مفعّلاً حاليًا، ويمكنك استخدام هذه الوسيطة لإيقاف معالِجك مؤقتًا
استنادًا إلى حالة المكوّن. سيتمّ استدعاء دالة lambda اللاحقة إذا بدأ
المستخدم حدثًا للعودة إلى النظام، وكان دالة
BackHandler
مفعّلة حاليًا.
ViewModel
إذا كنت تستخدم مكتبة Architecture Components
ViewModel، يمكنك الوصول إلى ViewModel
من أي عنصر قابل للتجميع من خلال
استدعاء الدالة
viewModel()
. أضِف التبعية التالية إلى ملف Gradle:
رائع
dependencies { implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.8.5' }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.5") }
يمكنك بعد ذلك استخدام الدالة viewModel()
في الرمز البرمجي.
class MyViewModel : ViewModel() { /*...*/ } // import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( viewModel: MyViewModel = viewModel() ) { // use viewModel here }
تعرِض viewModel()
ViewModel
حاليًا أو تنشئ ViewModel
جديدًا. بشكلٍ تلقائي،
يكون نطاق ViewModel
المعروض محصورًا بالنشاط أو المقتطف أو
وجهة التنقّل المحيطة، ويتم الاحتفاظ به ما دام النطاق نشطًا.
على سبيل المثال، إذا تم استخدام العنصر القابل للتجميع في نشاط، تعرض viewModel()
الرمز المرجعي نفسه إلى أن ينتهي النشاط أو يتم إنهاء العملية.
class MyViewModel : ViewModel() { /*...*/ } // import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( // Returns the same instance as long as the activity is alive, // just as if you grabbed the instance from an Activity or Fragment viewModel: MyViewModel = viewModel() ) { /* ... */ } @Composable fun MyScreen2( viewModel: MyViewModel = viewModel() // Same instance as in MyScreen ) { /* ... */ }
إرشادات الاستخدام
يمكنك عادةً الوصول إلى نُسخ ViewModel
في مكوّنات
على مستوى الشاشة، أي بالقرب من مكوّن جذر يتم استدعاؤه من نشاط أو fragment أو وجهة لرسم بياني للتنقّل. ويعود السبب في ذلك إلى أنّ ViewModel
s
تكون تلقائيًا مقيّدة بعناصر مستوى الشاشة هذه. يمكنك الاطّلاع على مزيد من المعلومات عن
دورة حياةViewModel
ومدى نطاقها.
حاول تجنُّب تمرير مثيلات
ViewModel
إلى عناصر قابلة للتجميع أخرى، لأنّ ذلك قد يجعل اختبار هذه العناصر
أكثر صعوبة وقد يؤدي إلى إيقاف
العروض الترويجية. بدلاً من ذلك، يمكنك تمرير البيانات
والدوالّ التي يحتاجون إليها فقط كمَعلمات.
يمكنك استخدام نُسخ ViewModel
لمحاولة
إدارة حالة العناصر القابلة للتجميع على مستوى الشاشة الفرعية، ولكن عليك الانتباه إلى
دورة حياةViewModel
ونطاقها. إذا كان العنصر القابل للتجميع مكتفيًا ذاتيًا، ننصحك باستخدام Hilt لحقن ViewModel
لتجنُّب الحاجة إلى تمرير التبعيات من العناصر القابلة للتجميع الرئيسية.
إذا كانت ViewModel
تحتوي على تبعيات، تأخذ viewModel()
مَعلمة اختيارية
ViewModelProvider.Factory
.
لمزيد من المعلومات عن ViewModel
في Compose وكيفية استخدام النُسخ
مع مكتبة Navigation Compose أو الأنشطة والمقاطع،
اطّلِع على مستندات التشغيل التفاعلي.
مصادر البيانات
تأتي ميزة "الإنشاء" مع إضافات للحلول المستندة إلى البث الأكثر رواجًا على Android. يتم توفير كلٍّ من هذه الإضافات من خلال عنصر مختلف:
- تم تضمين
LiveData.observeAsState()
في العنصرandroidx.compose.runtime:runtime-livedata:$composeVersion
. - لا يتطلب
Flow.collectAsState()
استخدام أيّ مكتبات إضافية. Observable.subscribeAsState()
مضمّنة في عنصرandroidx.compose.runtime:runtime-rxjava2:$composeVersion
أوandroidx.compose.runtime:runtime-rxjava3:$composeVersion
يتم تسجيل هذه العناصر كمستمع وتمثيل القيم على أنّها
State
. عند بث قيمة جديدة، يعيد Compose إعادة تركيب أجزاء واجهة المستخدم التي يتم فيها استخدام state.value
. على سبيل المثال، في هذا الرمز البرمجي، تتم إعادة تركيب ShowData
كلّما بثّexampleLiveData
قيمة جديدة.
// import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( viewModel: MyViewModel = viewModel() ) { val dataExample = viewModel.exampleLiveData.observeAsState() // Because the state is read here, // MyScreen recomposes whenever dataExample changes. dataExample.value?.let { ShowData(dataExample) } }
العمليات غير المتزامنة في ميزة "الإنشاء"
يتيح لك Jetpack Compose تنفيذ عمليات غير متزامنة باستخدام سلاسل الاستدعاء المتعدّدة من داخل العناصر القابلة للتجميع.
اطّلِع على واجهات برمجة التطبيقات LaunchedEffect
وproduceState
وrememberCoroutineScope
في
مستندات التأثيرات الجانبية للحصول على مزيد من
المعلومات.
التنقّل
يقدّم مكوّن التنقّل دعمًا لتطبيقات Jetpack Compose. اطّلِع على التنقّل باستخدام Compose و نقل بيانات واجهة مستخدم التنقّل في Jetpack إلى واجهة Compose للتنقّل للحصول على مزيد من المعلومات.
Hilt
Hilt هو الحلّ المُقترَح لحقن التبعية في تطبيقات Android، ويتكامل بسلاسة مع Compose.
تستخدم دالة viewModel()
المذكورة في قسم ViewModel
تلقائيًا ViewModel التي تنشئها Hilt باستخدام التعليق التوضيحي @HiltViewModel
. لقد قدّمنا مستندات تتضمّن معلومات عن دمج ViewModel في Hilt.
@HiltViewModel class MyViewModel @Inject constructor( private val savedStateHandle: SavedStateHandle, private val repository: ExampleRepository ) : ViewModel() { /* ... */ } // import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( viewModel: MyViewModel = viewModel() ) { /* ... */ }
Hilt وNavigation
يمكن أيضًا دمج Hilt مع مكتبة Navigation Compose. أضِف الملحقات التالية الإضافية إلى ملف Gradle:
رائع
dependencies { implementation 'androidx.hilt:hilt-navigation-compose:1.2.0' }
Kotlin
dependencies { implementation("androidx.hilt:hilt-navigation-compose:1.2.0") }
عند استخدام ميزة "إنشاء مسار تنقّل"، استخدِم دائمًا الدالة القابلة للتجميع hiltViewModel
للحصول على مثيل من @HiltViewModel
ViewModel
المُشارَك عليه تعليقات توضيحية.
ويعمل هذا مع الأجزاء أو الأنشطة التي تمّت إضافة تعليقات توضيحية إليها باستخدام الرمز
@AndroidEntryPoint
.
على سبيل المثال، إذا كان ExampleScreen
وجهة في رسم بياني للتنقّل،
اتصل بـ hiltViewModel()
للحصول على مثيل من ExampleViewModel
على مستوى
الوجهة كما هو موضّح في مقتطف الرمز البرمجي أدناه:
// import androidx.hilt.navigation.compose.hiltViewModel @Composable fun MyApp() { val navController = rememberNavController() val startRoute = "example" NavHost(navController, startDestination = startRoute) { composable("example") { backStackEntry -> // Creates a ViewModel from the current BackStackEntry // Available in the androidx.hilt:hilt-navigation-compose artifact val viewModel = hiltViewModel<MyViewModel>() MyScreen(viewModel) } /* ... */ } }
إذا كنت بحاجة إلى استرداد مثيل ViewModel
على مستوى
مسارات التنقّل أو الرسم البياني للتنقّل
بدلاً من ذلك، استخدِم الدالة القابلة للتجميع hiltViewModel
وأرسِل
backStackEntry
المطابق كمَعلمة:
// import androidx.hilt.navigation.compose.hiltViewModel // import androidx.navigation.compose.getBackStackEntry @Composable fun MyApp() { val navController = rememberNavController() val startRoute = "example" val innerStartRoute = "exampleWithRoute" NavHost(navController, startDestination = startRoute) { navigation(startDestination = innerStartRoute, route = "Parent") { // ... composable("exampleWithRoute") { backStackEntry -> val parentEntry = remember(backStackEntry) { navController.getBackStackEntry("Parent") } val parentViewModel = hiltViewModel<ParentViewModel>(parentEntry) ExampleWithRouteScreen(parentViewModel) } } } }
ترقيم الصفحات
تسهِّل عليك مكتبة
الفهرسة carregar تحميل البيانات تدريجيًا، وهي متوافقة مع ميزة "الإنشاء".
تحتوي صفحة إصدار الفهرسة على
معلومات عن تبعية paging-compose
الإضافية التي يجب إضافتها
إلى المشروع وإصداره.
في ما يلي مثال على واجهات برمجة تطبيقات Compose في مكتبة Paging:
@Composable fun MyScreen(flow: Flow<PagingData<String>>) { val lazyPagingItems = flow.collectAsLazyPagingItems() LazyColumn { items( lazyPagingItems.itemCount, key = lazyPagingItems.itemKey { it } ) { index -> val item = lazyPagingItems[index] Text("Item is $item") } } }
اطّلِع على مستندات القوائم والشبكات للحصول على مزيد من المعلومات عن استخدام ميزة "التنقّل في الصفحة" في ميزة "الإنشاء".
Maps
يمكنك استخدام مكتبة إنشاء خرائط لتوفير "خرائط Google" في تطبيقك. في ما يلي مثال على الاستخدام:
@Composable fun MapsExample() { val singapore = LatLng(1.35, 103.87) val cameraPositionState = rememberCameraPositionState { position = CameraPosition.fromLatLngZoom(singapore, 10f) } GoogleMap( modifier = Modifier.fillMaxSize(), cameraPositionState = cameraPositionState ) { Marker( state = remember { MarkerState(position = singapore) }, title = "Singapore", snippet = "Marker in Singapore" ) } }
أفلام مُقترَحة لك
- ملاحظة: يتم عرض نص الرابط عندما تكون لغة JavaScript غير مفعّلة.
- الآثار الجانبية في ميزة "الإنشاء"
- State وJetpack Compose
- حفظ حالة واجهة المستخدم في ميزة "الإنشاء"