प्रॉडक्ट से जुड़ी खबरें

Jetpack Compose की अप्रैल '26 की रिलीज़ में नया क्या है

पढ़ने में 6 मिनट लगेंगे
मेघन मेहता की प्रोफ़ाइल देखें
Meghan Mehta डेवलपर एडवोकेट, Android

आज, Jetpack Compose का 26 अप्रैल वाला वर्शन स्टेबल हो गया है. इस रिलीज़ में, Compose के मुख्य मॉड्यूल का वर्शन 1.11 शामिल है. पूरी BOM मैपिंग देखें. इसमें शेयर किए गए एलिमेंट को डीबग करने वाले टूल, ट्रैकपैड इवेंट वगैरह भी शामिल हैं. हमारे पास कुछ एक्सपेरिमेंटल एपीआई भी हैं. हम चाहते हैं कि आप इन्हें आज़माएं और इनके बारे में हमें सुझाव/राय दें या शिकायत करें.

आज की रिलीज़ का इस्तेमाल करने के लिए, अपने Compose BOM वर्शन को यहां दिए गए वर्शन पर अपग्रेड करें:

implementation(platform("androidx.compose:compose-bom:2026.04.01"))

Compose 1.11.0 में हुए बदलाव

टेस्ट में कोरूटीन का इस्तेमाल करना

हम कंपोज़र में, टेस्ट के समय को मैनेज करने के तरीके में एक बड़ा अपडेट कर रहे हैं. Compose 1.10 में बताए गए ऑप्ट-इन की अवधि के बाद, v2 टेस्टिंग एपीआई अब डिफ़ॉल्ट रूप से उपलब्ध हैं. साथ ही, v1 एपीआई अब काम नहीं करते. मुख्य बदलाव यह है कि डिफ़ॉल्ट टेस्ट डिस्पैचर बदल गया है. v1 API, UnconfinedTestDispatcher पर निर्भर करते थे. यह को-रूटीन को तुरंत एक्ज़ीक्यूट करता था. वहीं, v2 API, StandardTestDispatcher का इस्तेमाल करते हैं. इसका मतलब है कि आपकी जांचों में जब कोई को-रूटीन लॉन्च किया जाता है, तो उसे अब कतार में रखा जाता है. साथ ही, वर्चुअल क्लॉक के आगे बढ़ने तक उसे लागू नहीं किया जाता.

इससे प्रोडक्शन की स्थितियों को बेहतर तरीके से सिम्युलेट किया जा सकता है. साथ ही, रेस कंडीशन को असरदार तरीके से खत्म किया जा सकता है. इससे आपकी टेस्ट सुइट ज़्यादा मज़बूत और कम फ़्लेकी हो जाती है.

हमारा सुझाव है कि आप अपनी टेस्ट सुइट को माइग्रेट करें, ताकि यह पक्का किया जा सके कि आपके टेस्ट, स्टैंडर्ड कोरूटीन के साथ काम करते हैं. साथ ही, आने वाले समय में कंपैटिबिलिटी से जुड़ी समस्याओं से बचा जा सके. एपीआई मैपिंग और सामान्य फ़िक्स के लिए, हमारी पूरी जानकारी वाली माइग्रेशन गाइड देखें.

शेयर किए गए एलिमेंट में सुधार और ऐनिमेशन टूलिंग

हमने शेयर किए गए एलिमेंट और Modifier.animatedBounds के लिए, कुछ काम के विज़ुअल डीबगिंग टूल भी जोड़े हैं. अब आपको यह पता चल सकता है कि पर्दे के पीछे क्या हो रहा है. जैसे, टारगेट बाउंड्री, ऐनिमेशन ट्रैजेक्ट्री, और कितने मैच मिले. इससे यह पता लगाना आसान हो जाता है कि ट्रांज़िशन आपकी उम्मीद के मुताबिक क्यों काम नहीं कर रहा है. नई टूलिंग का इस्तेमाल करने के लिए, बस अपने SharedTransitionLayout को LookaheadAnimationVisualDebugging कंपोज़ेबल से घेरें. 

LookaheadAnimationVisualDebugging(
    overlayColor = Color(0x4AE91E63),
    isEnabled = true,
    multipleMatchesColor = Color.Green,
    isShowKeylabelEnabled = false,
    unmatchedElementColor = Color.Red,
) {
    SharedTransitionLayout {
        CompositionLocalProvider(
            LocalSharedTransitionScope provides this,
        ) {
            // your content
        }
    }
}

ट्रैकपैड इवेंट

हमने ट्रैकपैड के लिए, कंपोज़ करने की सुविधा को बेहतर बनाया है. जैसे, लैपटॉप में पहले से मौजूद ट्रैकपैड, टैबलेट से अटैच किए जा सकने वाले ट्रैकपैड या बाहरी/वर्चुअल ट्रैकपैड. अब सामान्य तौर पर, बेसिक ट्रैकपैड इवेंट को PointerType.Mouse इवेंट माना जाएगा. इससे माउस और ट्रैकपैड के व्यवहार को एक जैसा किया जा सकेगा, ताकि उपयोगकर्ता की उम्मीदों को बेहतर तरीके से पूरा किया जा सके. पहले, इन ट्रैकपैड इवेंट को PointerType.Touch की नकली टचस्क्रीन उंगलियों के तौर पर माना जाता था. इससे उपयोगकर्ताओं को भ्रम होता था. उदाहरण के लिए, ट्रैकपैड से क्लिक करके खींचने पर, चुनने के बजाय स्क्रोल होगा. Compose की नई रिलीज़ में, इन इवेंट के पॉइंटर टाइप को बदल दिया गया है. इसलिए, अब ट्रैकपैड से क्लिक और ड्रैग करने पर स्क्रोल नहीं होगा.

हमने एपीआई 34 के बाद से, प्लैटफ़ॉर्म पर पहचाने गए ज़्यादा मुश्किल ट्रैकपैड जेस्चर के लिए भी सहायता जोड़ी है. इनमें दो उंगलियों से स्वाइप करना और पिंच करना शामिल है. इन जेस्चर को Modifier.scrollable और Modifier.transformable जैसे कॉम्पोनेंट अपने-आप पहचान लेते हैं, ताकि ट्रैकपैड के साथ बेहतर तरीके से काम किया जा सके.

इन बदलावों से, बिल्ट-इन कॉम्पोनेंट में ट्रैकपैड के काम करने के तरीके को बेहतर बनाया गया है. इसमें, टच स्लोप की सुविधा को हटाया गया है. साथ ही, ड्रैग-एंड-ड्रॉप करने के लिए ज़्यादा आसान जेस्चर, टेक्स्ट फ़ील्ड में डबल-क्लिक और ट्रिपल-क्लिक करके चुनने की सुविधा, और टेक्स्ट फ़ील्ड में डेस्कटॉप स्टाइल वाले कॉन्टेक्स्ट मेन्यू शामिल हैं.

ट्रैकपैड के व्यवहार की जांच करने के लिए, performTrackpadInput, के साथ नए टेस्टिंग एपीआई उपलब्ध हैं. इनकी मदद से, ट्रैकपैड के साथ इस्तेमाल किए जाने पर, अपने ऐप्लिकेशन के व्यवहार की पुष्टि की जा सकती है. अगर आपके पास कस्टम जेस्चर डिटेक्टर हैं, तो इनपुट टाइप के हिसाब से उनके व्यवहार की पुष्टि करें. जैसे, टचस्क्रीन, माउस, ट्रैकपैड, और स्टाइलस. साथ ही, यह पक्का करें कि वे माउस के स्क्रोल व्हील और ट्रैकपैड के जेस्चर के साथ काम करते हों.

beforeAndAfter.webp

कंपोज़िशन होस्ट की डिफ़ॉल्ट सेटिंग (Compose runtime)

हमने HostDefaultProvider, LocalHostDefaultProvider, HostDefaultKey, और ViewTreeHostDefaultKey को पेश किया है, ताकि होस्ट-लेवल की सेवाओं को सीधे तौर पर compose-runtime के ज़रिए उपलब्ध कराया जा सके. इससे लाइब्रेरी को लुकअप के लिए, compose-ui पर निर्भर नहीं रहना पड़ता. साथ ही, Kotlin Multiplatform को बेहतर तरीके से सपोर्ट किया जा सकता है. इन वैल्यू को कंपोज़िशन ट्री से लिंक करने के लिए, लाइब्रेरी के लेखक compositionLocalWithHostDefaultOf का इस्तेमाल करके CompositionLocal बना सकते हैं. इससे होस्ट से डिफ़ॉल्ट वैल्यू तय की जा सकती हैं.

रैपर की झलक देखना

Android Studio में कस्टम प्रीव्यू एक नई सुविधा है. इसकी मदद से, यह तय किया जा सकता है कि Compose प्रीव्यू का कॉन्टेंट कैसे दिखाया जाए.

PreviewWrapperProvider इंटरफ़ेस लागू करके और नया @PreviewWrapper एनोटेशन लागू करके, कस्टम लॉजिक को आसानी से इंजेक्ट किया जा सकता है. जैसे, कोई खास Theme लागू करना. इस एनोटेशन को @Composable और @Preview या @MultiPreview के साथ एनोटेट किए गए फ़ंक्शन पर लागू किया जा सकता है. इससे एक सामान्य और आसानी से इस्तेमाल किया जा सकने वाला समाधान मिलता है. यह समाधान, पूर्वावलोकन की सुविधाओं के साथ काम करता है और बार-बार इस्तेमाल होने वाले कोड को काफ़ी हद तक कम करता है.

class ThemeWrapper: PreviewWrapperProvider {
    @Composable
    override fun Wrap(content: @Composable (() -> Unit)) {
        JetsnackTheme {
            content()
        }
    }
}


@PreviewWrapper(ThemeWrapper::class)
@Preview
@Composable
private fun ButtonPreview() {
    // JetsnackTheme in effect
    Button(onClick = {}) {
        Text(text = "Demo")
    }
}

बंद की गई सेवाएं/सुविधाएं और हटाए गए फ़ील्ड

  • Compose 1.10 की ब्लॉग पोस्ट में बताए गए तरीके के मुताबिक, हम Modifier.onFirstVisible() को बंद कर रहे हैं. इसके नाम की वजह से अक्सर गलतफ़हमियां होती थीं. खास तौर पर, लेज़ी लेआउट में ऐसा होता था, जहां स्क्रोल करने के दौरान यह कई बार ट्रिगर होता था. हमारा सुझाव है कि आप Modifier.onVisibilityChanged() पर माइग्रेट करें. इससे, इस्तेमाल के खास उदाहरणों की ज़रूरतों के हिसाब से, दिखने की स्थितियों को मैन्युअल तरीके से ज़्यादा सटीक तरीके से ट्रैक किया जा सकता है.
  • ComposeFoundationFlags.isTextFieldDpadNavigationEnabled फ़्लैग को हटा दिया गया है, क्योंकि अब TextFields के लिए डी-पैड नेविगेशन की सुविधा डिफ़ॉल्ट रूप से हमेशा चालू रहती है. नए वर्शन में, यह पक्का किया जाता है कि गेमपैड या टीवी रिमोट से डी-पैड इवेंट, सबसे पहले कर्सर को दी गई दिशा में ले जाएं. कर्सर के टेक्स्ट के आखिर में पहुंचने पर ही, फ़ोकस को किसी दूसरे एलिमेंट पर ले जाया जा सकता है.

आने वाले एपीआई

Compose 1.12.0 की आने वाली रिलीज़ में, compileSdk को compileSdk 37 पर अपग्रेड किया जाएगा. साथ ही, AGP 9 और Compose पर निर्भर रहने वाले सभी ऐप्लिकेशन और लाइब्रेरी के लिए, यह ज़रूरी शर्त लागू होगी. हमारा सुझाव है कि आप रिलीज़ किए गए नए वर्शन के बारे में अप-टू-डेट रहें. ऐसा इसलिए, क्योंकि Compose का मकसद नई compileSdks को तुरंत अपनाना है, ताकि Android की नई सुविधाओं का ऐक्सेस दिया जा सके. अलग-अलग एपीआई लेवल के लिए, AGP के किस वर्शन का इस्तेमाल किया जा सकता है, इस बारे में ज़्यादा जानने के लिए, यहां दिया गया दस्तावेज़ ज़रूर देखें. 

Compose 1.11.0 में, इन एपीआई को @Experimental के तौर पर पेश किया गया है. हम चाहते हैं कि आप इन्हें अपने ऐप्लिकेशन में आज़माएं और हमें अपने सुझाव, शिकायत या राय दें. ध्यान दें कि @Experimental APIs को शुरुआती तौर पर समीक्षा और सुझाव/राय देने के लिए उपलब्ध कराया जाता है. आने वाले समय में, इनमें बड़े बदलाव किए जा सकते हैं या इन्हें हटाया जा सकता है.

स्टाइल (एक्सपेरिमेंट के तौर पर उपलब्ध)

हम स्टाइलिंग के लिए, एक्सपेरिमेंट के तौर पर एक नया फ़ाउंडेशन एपीआई लॉन्च कर रहे हैं. Style API, कॉम्पोनेंट के विज़ुअल एलिमेंट को पसंद के मुताबिक बनाने का एक नया तरीका है. पहले, यह काम मॉडिफ़ायर की मदद से किया जाता था. इसे ज़्यादा बेहतर तरीके से और आसानी से पसंद के मुताबिक बनाने के लिए डिज़ाइन किया गया है. इसके लिए, स्टाइल की जा सकने वाली प्रॉपर्टी का स्टैंडर्ड सेट उपलब्ध कराया जाता है. इसमें स्टेट के आधार पर स्टाइलिंग और ऐनिमेशन वाले ट्रांज़िशन को आसानी से इस्तेमाल किया जा सकता है. इस नए एपीआई की मदद से, हमें परफ़ॉर्मेंस से जुड़े फ़ायदे मिल रहे हैं. हम Style API के स्थिर होने के बाद, Material कॉम्पोनेंट में स्टाइल इस्तेमाल करने का प्लान बना रहे हैं.

दबाए गए बटन के बैकग्राउंड की स्टाइल को बदलने का एक बुनियादी उदाहरण:

@Composable
fun LoginButton(modifier: Modifier = Modifier) {
    Button(
        onClick = {
            // Login logic
        },
        modifier = modifier,
        style = {
            background(
                Brush.linearGradient(
                    listOf(lightPurple, lightBlue)
                )
            )
            width(75.dp)
            height(50.dp)
            textAlign(TextAlign.Center)
            externalPadding(16.dp)

            pressed {
                background(
                    Brush.linearGradient(
                        listOf(Color.Magenta, Color.Red)
                    )
                )
            }
        }
    ){
        Text(
            text = "Login",
        )
    }
}
styles.webp

दस्तावेज़ देखें और किसी भी गड़बड़ी की शिकायत यहां करें.

MediaQuery (एक्सपेरिमेंट के तौर पर उपलब्ध)

नए mediaQuery एपीआई की मदद से, यूज़र इंटरफ़ेस (यूआई) को उसके एनवायरमेंट के हिसाब से अडजस्ट किया जा सकता है. यह एपीआई, यूज़र इंटरफ़ेस (यूआई) को अडजस्ट करने का एक बेहतर तरीका है. यह UiMediaScope में, मुश्किल जानकारी को आसानी से समझने वाली शर्तों में बदल देता है. इससे यह पक्का होता है कि जानकारी को सिर्फ़ तब फिर से कंपोज़ किया जाए, जब इसकी ज़रूरत हो.

इसमें कई तरह के एनवायरमेंटल सिग्नल इस्तेमाल किए जा सकते हैं. जैसे, डिवाइस की क्षमताएं (कीबोर्ड के टाइप और पॉइंटर की सटीक जानकारी) और कॉन्टेक्स्ट की स्थितियां (विंडो का साइज़ और पोस्चर). इससे, बेहतर तरीके से काम करने वाले अनुभव बनाए जा सकते हैं. derivedMediaQuery की मदद से, परफ़ॉर्मेंस को बेहतर बनाया जाता है, ताकि ज़्यादा फ़्रीक्वेंसी वाले अपडेट को मैनेज किया जा सके. साथ ही, स्कोप को बदलने की सुविधा से, अलग-अलग हार्डवेयर कॉन्फ़िगरेशन पर टेस्टिंग और प्रीव्यू को आसानी से किया जा सकता है. पहले, किसी डिवाइस की कुछ प्रॉपर्टी का ऐक्सेस पाने के लिए, आपको बहुत सारा बॉयलरप्लेट लिखना पड़ता था. जैसे, अगर कोई डिवाइस टेबलटॉप मोड में है, तो आपको यह बॉयलरप्लेट लिखना पड़ता था: 

@Composable
fun isTabletopPosture(
    context: Context = LocalContext.current
): Boolean {
    val windowLayoutInfo by
        WindowInfoTracker
            .getOrCreate(context)
            .windowLayoutInfo(context)
            .collectAsStateWithLifecycle(null)

    return windowLayoutInfo.displayFeatures.any { displayFeature ->
        displayFeature is FoldingFeature &&
            displayFeature.state == FoldingFeature.State.HALF_OPENED &&
            displayFeature.orientation == FoldingFeature.Orientation.HORIZONTAL
    }
}

@Composable
fun VideoPlayer() {
    if(isTabletopPosture()) {
        TabletopLayout()
    } else {
        FlatLayout()
    }
}

अब UIMediaQuery की मदद से, डिवाइस की प्रॉपर्टी के बारे में क्वेरी करने के लिए, mediaQuery सिंटैक्स जोड़ा जा सकता है. जैसे, अगर कोई डिवाइस टेबलटॉप मोड में है, तो:

@OptIn(ExperimentalMediaQueryApi::class)
@Composable
fun VideoPlayer() {
    if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) {
        TabletopLayout()
    } else {
        FlatLayout()
    }
}

दस्तावेज़ देखें और किसी भी गड़बड़ी की शिकायत यहां करें.

ग्रिड (एक्सपेरिमेंट के तौर पर उपलब्ध)

Grid, Jetpack Compose में मुश्किल और दो डाइमेंशन वाले लेआउट बनाने के लिए एक नया और बेहतरीन एपीआई है. Row और Column, लीनियर डिज़ाइन के लिए बेहतरीन हैं. वहीं, Grid की मदद से, आपको स्क्रीन-लेवल के आर्किटेक्चर और जटिल कॉम्पोनेंट पर स्ट्रक्चरल कंट्रोल मिलता है. साथ ही, स्क्रोल की जा सकने वाली सूची का इस्तेमाल करने की ज़रूरत नहीं पड़ती. Grid की मदद से, ट्रैक, गैप, और सेल का इस्तेमाल करके लेआउट तय किया जा सकता है. इसमें साइज़ के लिए, Dp, प्रतिशत, कॉन्टेंट के इंट्रिंसिक साइज़, और फ़्लेक्सिबल "Fr" यूनिट जैसे विकल्प मिलते हैं. 

@OptIn(ExperimentalGridApi::class)
@Composable
fun GridExample() {
    Grid(
        config = {
            repeat(4) { column(0.25f) }
            repeat(2) { row(0.5f) }
            gap(16.dp)
        }
    ) {
        Card1(modifier = Modifier.gridItem(rowSpan = 2)
        Card2(modifier = Modifier.gridItem(colmnSpan = 3)
        Card3(modifier = Modifier.gridItem(columnSpan = 2)
        Card4()
    }
}

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

Grid.gif

दस्तावेज़ देखें और किसी भी गड़बड़ी की शिकायत यहां करें. 

FlexBox (Experimental)

FlexBox एक लेआउट कंटेनर है. इसे बेहतर परफ़ॉर्मेंस और अडैप्टिव यूज़र इंटरफ़ेस (यूआई) के लिए डिज़ाइन किया गया है. यह उपलब्ध कंटेनर डाइमेंशन के आधार पर, आइटम के साइज़ और स्पेस डिस्ट्रिब्यूशन को मैनेज करता है.  यह रैपिंग (wrap) और आइटम के मल्टी-ऐक्सिस अलाइनमेंट (justifyContent, alignItems, alignContent) जैसे मुश्किल टास्क को हैंडल करता है. इससे आइटम को कंटेनर में फ़िट करने के लिए, बड़ा (grow) या छोटा (shrink) किया जा सकता है. 

@OptIn(ExperimentalFlexBoxApi::class)
fun FlexBoxWrapping(){
    FlexBox(
        config = {
            wrap(FlexWrap.Wrap)
            gap(8.dp)
        }
    ) {
        RedRoundedBox()
        BlueRoundedBox()
        GreenRoundedBox(modifier = Modifier.width(350.dp).flex { grow(1.0f) })
        OrangeRoundedBox(modifier = Modifier.width(200.dp).flex { grow(0.7f) })
        PinkRoundedBox(modifier = Modifier.width(200.dp).flex { grow(0.3f) })
    }
}
AnimationGif.gif

दस्तावेज़ देखें और किसी भी गड़बड़ी की शिकायत यहां करें.

SlotTable को लागू करने का नया तरीका (एक्सपेरिमेंट के तौर पर उपलब्ध)

हमने SlotTable को लागू करने का एक नया तरीका पेश किया है. यह इस रिलीज़ में डिफ़ॉल्ट रूप से बंद होता है. SlotTable एक इंटरनल डेटा स्ट्रक्चर है. इसका इस्तेमाल Compose रनटाइम, कंपोज़िशन के क्रम की स्थिति को ट्रैक करने, अमान्यताओं/रीकंपोज़िशन को ट्रैक करने, याद रखी गई वैल्यू को सेव करने, और रनटाइम में कंपोज़िशन के सभी मेटाडेटा को ट्रैक करने के लिए करता है. इस नए तरीके को परफ़ॉर्मेंस को बेहतर बनाने के लिए डिज़ाइन किया गया है. खास तौर पर, रैंडम बदलावों के लिए.

नई SlotTable को आज़माने के लिए, ComposeRuntimeFlags.isLinkBufferComposerEnabled को चालू करें. 

आज ही कोडिंग शुरू करें!

Jetpack Compose में कई नए और शानदार एपीआई उपलब्ध हैं. साथ ही, कई और एपीआई जल्द ही उपलब्ध होने वाले हैं. इसलिए, Jetpack Compose पर माइग्रेट करने का यह सबसे सही समय है.  हमेशा की तरह, हम आपके सुझाव, शिकायत या राय और सुविधाओं के अनुरोधों का स्वागत करते हैं. खास तौर पर, @Experimental ऐसी सुविधाओं के बारे में जो अब भी डेवलपमेंट के चरण में हैं. कृपया इन्हें यहां सबमिट करें. ईमेल लिखने का आनंद लें!

लेखक:
पढ़ना जारी रखें