लिखें और अन्य लाइब्रेरी

Compose में अपनी पसंदीदा लाइब्रेरी का इस्तेमाल किया जा सकता है. इस सेक्शन में बताया गया है कि में कुछ सबसे उपयोगी लाइब्रेरी शामिल हैं.

गतिविधि

किसी गतिविधि में कंपोज़ की सुविधा इस्तेमाल करने के लिए, आपको ComponentActivity, Activity की एक सब-क्लास जो सही LifecycleOwner और कॉम्पोनेंट शामिल करें. यह अन्य एपीआई भी उपलब्ध कराता है, जो आपके कोड को आपकी गतिविधि क्लास में मौजूद, ओवरराइड करने वाले तरीकों से अलग करते हैं. 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() कानूनी समझौता. बटन पर टैप करने से अनुरोध लॉन्च हो जाता है. इसके लिए ट्रेलिंग लैम्डा rememberLauncherForActivityResult() जब उपयोगकर्ता कोई इमेज चुनता है और लॉन्च की गतिविधि पर वापस जाता है, तो यह सेवा चालू हो जाती है. यह कॉइल के rememberImagePainter() का इस्तेमाल करके चुनी गई इमेज को लोड करता है फ़ंक्शन का इस्तेमाल करना होगा.

इसकी कोई भी सब-क्लास ActivityResultContract का इस्तेमाल पहले आर्ग्युमेंट के तौर पर किया जा सकता है rememberLauncherForActivityResult(). इसका मतलब है कि इस तकनीक का इस्तेमाल, फ़्रेमवर्क और अन्य सामान्य पैटर्न से कॉन्टेंट का अनुरोध करने के लिए किया जा सकता है. अपना खुद का इंटरैक्शन भी बनाया जा सकता है कस्टम अनुबंधों और उनका इस्तेमाल इस तकनीक को अपनाएं.

रनटाइम की अनुमतियों का अनुरोध किया जा रहा है

ऊपर बताए गए Activity Result API और rememberLauncherForActivityResult() का इस्तेमाल, एक ही अनुमति के लिए RequestPermission कन्ट्रैक्ट या कई अनुमतियों के लिए RequestMultiplePermissions कन्ट्रैक्ट का इस्तेमाल करके, रनटाइम की अनुमतियों का अनुरोध करने के लिए किया जा सकता है.

असिस्टेंट की अनुमतियों की लाइब्रेरी का इस्तेमाल, उन एपीआई के ऊपर एक लेयर के तौर पर भी किया जा सकता है. इससे, अनुमतियों के लिए मिली मौजूदा स्थिति को उस स्थिति में मैप किया जा सकता है जिसका इस्तेमाल आपका Compose यूज़र इंटरफ़ेस (यूआई) कर सकता है.

सिस्टम के 'वापस जाएं' बटन को मैनेज करना

वापस जाने के लिए पसंद के मुताबिक नेविगेशन देना और सिस्टम के 'वापस जाएं' बटन के डिफ़ॉल्ट व्यवहार को ओवरराइड कर सकते हैं कंपोज़ेबल, तो आपका कंपोज़ेबल, BackHandler इवेंट को रोकने के लिए:

var backHandlingEnabled by remember { mutableStateOf(true) }
BackHandler(backHandlingEnabled) {
    // Handle back press
}

पहला आर्ग्युमेंट यह कंट्रोल करता है कि BackHandler फ़िलहाल चालू है या नहीं. इस आर्ग्युमेंट का इस्तेमाल करके, अपने कॉम्पोनेंट की स्थिति के आधार पर, हैंडलर को कुछ समय के लिए बंद किया जा सकता है. अगर उपयोगकर्ता सिस्टम वापस लाने वाले किसी इवेंट को ट्रिगर करता है और 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() गतिविधि समाप्त होने या प्रक्रिया पूरी होने तक उसी इंस्टेंस में नहीं बदलाव किए जा सकते.

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 इंस्टेंस ऐक्सेस किए जाते हैं कंपोज़ेबल, जो किसी गतिविधि से कॉल किए जाने वाले रूट कंपोज़ेबल के आस-पास होते हैं, फ़्रैगमेंट या नेविगेशन ग्राफ़ का डेस्टिनेशन. ऐसा इसलिए हुआ, क्योंकि ViewModel से डिफ़ॉल्ट रूप से, उनका दायरा उन स्क्रीन लेवल ऑब्जेक्ट तक होता है. ViewModel के लाइफ़साइकल और दायरे के बारे में ज़्यादा जानने के लिए, यहां पढ़ें.

ViewModel इंस्टेंस को अन्य कॉम्पोज़ेबल में पास करने से बचें, क्योंकि इससे उन कॉम्पोज़ेबल को टेस्ट करना मुश्किल हो सकता है और झलक खराब हो सकती है. इसके बजाय, पैरामीटर के तौर पर सिर्फ़ वह डेटा और फ़ंक्शन पास करें जिनकी उन्हें ज़रूरत है.

सब-स्क्रीन-लेवल कॉम्पोज़ेबल के लिए स्टेटस मैनेज करने के लिए, ViewModel इंस्टेंस का इस्तेमाल किया जा सकता है. हालांकि, ViewModel के लाइफ़साइकल और दायरे के बारे में ज़रूर जानें. अगर कॉम्पोज़ेबल में सभी चीज़ें मौजूद हैं, तो ViewModel को इंजेक्ट करने के लिए Hilt का इस्तेमाल किया जा सकता है. इससे, पैरंट कॉम्पोज़ेबल से डिपेंडेंसी पास करने की ज़रूरत नहीं पड़ती.

अगर आपके ViewModel में डिपेंडेंसी हैं, तो viewModel() पैरामीटर के तौर पर वैकल्पिक ViewModelProvider.Factory का इस्तेमाल करता है.

Compose में ViewModel के बारे में ज़्यादा जानकारी पाने और 'नेविगेशन 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 पर माइग्रेट करना लेख पढ़ें.

हिल्ट

Android ऐप्लिकेशन में डिपेंडेंसी इंजेक्शन के लिए, Hilt का सुझाव दिया जाता है. यह Compose के साथ आसानी से काम करता है.

ViewModel सेक्शन में बताए गए viewModel() फ़ंक्शन में, @HiltViewModel एनोटेशन की मदद से Hilt के बनाए गए ViewModel का अपने-आप इस्तेमाल होता है. हमने 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 Compose लाइब्रेरी के साथ भी इंटिग्रेट होती है. इन्हें जोड़ें आपकी Gradle फ़ाइल के लिए अतिरिक्त डिपेंडेंसी:

Groovy

dependencies {
    implementation 'androidx.hilt:hilt-navigation-compose:1.2.0'
}

Kotlin

dependencies {
    implementation("androidx.hilt:hilt-navigation-compose:1.2.0")
}

नेविगेशन कॉम्पोज़ का इस्तेमाल करते समय, अपने @HiltViewModel एनोटेट किए गए ViewModel का कोई इंस्टेंस पाने के लिए, हमेशा hiltViewModel composable फ़ंक्शन का इस्तेमाल करें. यह उन फ़्रैगमेंट या गतिविधियों के साथ काम करता है जिनके साथ एनोटेट किया गया है @AndroidEntryPoint.

उदाहरण के लिए, अगर ExampleScreen नेविगेशन ग्राफ़ में कोई डेस्टिनेशन है, तो डेस्टिनेशन के दायरे में ExampleViewModel का कोई इंस्टेंस पाने के लिए, hiltViewModel() को कॉल करें. इस बारे में नीचे दिए गए कोड स्निपेट में बताया गया है:

// 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 API का एक उदाहरण दिया गया है:

@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

अपने ऐप्लिकेशन में Google Maps उपलब्ध कराने के लिए, Maps Compose लाइब्रेरी का इस्तेमाल किया जा सकता है. इसका इस्तेमाल करने का उदाहरण यहां दिया गया है:

@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"
        )
    }
}