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

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

पांच मिनट में पढ़ें
Meghan Mehta
डेवलपर एडवोकेट, Android

आज, Jetpack Compose का 26 अप्रैल वाला वर्शन स्टेबल है. इस रिलीज़ में, कोर कंपोज़ मॉड्यूल का वर्शन 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
        }
    }
}

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

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

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

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

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

beforeAndAfter.webp

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

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

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

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

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

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

@PreviewWrapperProvider(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 को शुरुआती तौर पर जांच करने और सुझाव/राय देने या शिकायत करने के लिए उपलब्ध कराया गया है. आने वाले समय में, इनमें बड़े बदलाव किए जा सकते हैं या इन्हें हटाया भी जा सकता है.@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 सुविधाओं के बारे में सुझाव, शिकायत या राय दें. कृपया इन्हें यहां सबमिट करें. म्यूज़िक बनाने का आनंद लें!

लेखक:

पढ़ना जारी रखें