يمكنك استخدام المكتبات المفضّلة لديك في Compose. يوضّح هذا القسم كيفية دمج بعض المكتبات الأكثر فائدة.
النشاط
لاستخدام 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
للحصول على أذونات متعددة.
يمكن أيضًا استخدام مكتبة أذونات Accompanist كطبقة أعلى من واجهات برمجة التطبيقات هذه لربط حالة الأذونات الممنوحة حاليًا بالحالة التي يمكن أن تستخدمها واجهة مستخدم Compose.
التعامل مع زر الرجوع في النظام
لتوفير عملية تنقّل مخصّصة للرجوع
وتجاوز السلوك التلقائي لزر الرجوع في النظام من داخل
العنصر القابل للإنشاء، يمكن أن يستخدم العنصر القابل للإنشاء
BackHandler
لاعتراض هذا الحدث:
var backHandlingEnabled by remember { mutableStateOf(true) } BackHandler(backHandlingEnabled) { // Handle back press }
يتحكّم الوسيط الأول في ما إذا كان
BackHandler
مفعّلاً حاليًا. يمكنك استخدام هذا الوسيط لإيقاف المعالج مؤقتًا
استنادًا إلى حالة المكوّن. سيتم استدعاء دالة lambda اللاحقة إذا فعّل المستخدم حدث الرجوع إلى الخلف في النظام، وكان BackHandler
مفعّلاً حاليًا.
ViewModel
إذا كنت تستخدم مكتبة ViewModel
في Architecture Components، يمكنك الوصول إلى
ViewModel
من أي عنصر قابل للإنشاء من خلال استدعاء الدالة
viewModel()
. أضِف الاعتمادية التالية إلى ملف Gradle:
Groovy
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
، ويتم الاحتفاظ به طالما أنّ النطاق نشط.
على سبيل المثال، إذا تم استخدام العنصر القابل للإنشاء في نشاط، ستعرض الدالة 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
في عناصر screen-level
القابلة للإنشاء، أي بالقرب من عنصر قابل للإنشاء أساسي يتم استدعاؤه من نشاط أو جزء أو وجهة في الرسم البياني للتنقّل. ويرجع ذلك إلى أنّ ViewModel
s
يتم تلقائيًا تحديد نطاقها ليشمل عناصر مستوى الشاشة. يمكنك الاطّلاع على مزيد من المعلومات حول دورة حياة ViewModel
's
ونطاقها هنا.
حاوِل تجنُّب تمرير مثيلات
ViewModel
إلى عناصر أخرى قابلة للإنشاء، لأنّ ذلك قد يصعّب اختبار هذه العناصر القابلة للإنشاء وقد يؤدي إلى إيقاف
المعاينات. بدلاً من ذلك، مرِّر البيانات والدوال التي يحتاجون إليها فقط كمعلَمات.
يمكنك استخدام مثيلات ViewModel
لإدارة الحالة في العناصر القابلة للإنشاء على مستوى الشاشة الفرعية، ولكن يجب الانتباه إلى دورة الحياة والنطاق الخاصين بـ ViewModel
. إذا كان العنصر القابل للإنشاء مكتفيًا ذاتيًا، يمكنك استخدام Hilt لتضمين ViewModel
وتجنُّب تمرير التبعيات من العناصر القابلة للإنشاء الرئيسية.
إذا كان ViewModel
يتضمّن تبعيات، تأخذ viewModel()
قيمة اختيارية
ViewModelProvider.Factory
كمَعلمة.
لمزيد من المعلومات حول ViewModel
في Compose وكيفية استخدام العناصر مع مكتبة Navigation Compose أو الأنشطة واللقطات، راجِع مستندات التشغيل التفاعلي.
مصادر البيانات
تتضمّن 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) } }
العمليات غير المتزامنة في Compose
تتيح لك Jetpack Compose تنفيذ عمليات غير متزامنة باستخدام إجراءات روتينية من داخل العناصر القابلة للإنشاء.
يمكنك الاطّلاع على واجهات برمجة التطبيقات LaunchedEffect
وproduceState
وrememberCoroutineScope
في مستندات الآثار الجانبية للحصول على مزيد من المعلومات.
التنقّل
يوفّر مكوِّن التنقّل إمكانية استخدام تطبيقات Jetpack Compose. اطّلِع على التنقّل باستخدام Compose ونقل Jetpack Navigation إلى Navigation Compose للحصول على مزيد من المعلومات.
Hilt
Hilt هو الحلّ المقترَح لتوفير التبعية في تطبيقات Android، ويتوافق بسلاسة مع Compose.
تستخدم الدالة viewModel()
المذكورة في قسم ViewModel تلقائيًا ViewModel الذي ينشئه Hilt باستخدام التعليق التوضيحي @HiltViewModel
. لقد وفّرنا مستندات تتضمّن معلومات حول دمج Hilt مع ViewModel.
@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:
Groovy
dependencies { implementation 'androidx.hilt:hilt-navigation-compose:1.2.0' }
Kotlin
dependencies { implementation("androidx.hilt:hilt-navigation-compose:1.2.0") }
عند استخدام Navigation Compose، استخدِم دائمًا الدالة القابلة للإنشاء hiltViewModel
للحصول على مثيل من ViewModel
الذي تمّت إضافة التعليقات التوضيحية إليه @HiltViewModel
.
تعمل هذه الميزة مع الرموز أو الأنشطة التي تمّت إضافة التعليقات التوضيحية إليها باستخدام
@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) } } } }
ترقيم الصفحات
تسهّل مكتبة
تقسيم الصفحات
عليك تحميل البيانات تدريجيًا، وهي متوافقة مع Compose.
تحتوي صفحة إصدار الترقيم إلى صفحات على معلومات حول التبعية الإضافية 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") } } }
راجِع مستندات القوائم والجداول للحصول على مزيد من المعلومات حول استخدام "تقسيم المحتوى إلى صفحات" في Compose.
Maps
يمكنك استخدام مكتبة Maps Compose لتوفير "خرائط 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 غير مفعّلة
- الآثار الجانبية في Compose
- الحالة وJetpack Compose
- حفظ حالة واجهة المستخدم في Compose