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

Jetpack Compose की दिसंबर '25 की रिलीज़ में नया क्या है

पढ़ने में 6 मिनट लगेंगे
निक बुचर की प्रोफ़ाइल देखें
Nick Butcher प्रॉडक्ट मैनेजर

आज, Jetpack Compose का दिसंबर 2025 वाला वर्शन स्टेबल है. इसमें Compose के मुख्य मॉड्यूल का वर्शन 1.10 और Material 3 का वर्शन 1.4 शामिल है. पूरी BOM मैपिंग देखें. इसमें नई सुविधाएं जोड़ी गई हैं और परफ़ॉर्मेंस में काफ़ी सुधार किया गया है.

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

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

परफ़ॉर्मेंस में सुधार

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

janky.png

स्क्रोल करने की परफ़ॉर्मेंस का बेंचमार्क. इसमें Compose के अलग-अलग वर्शन में व्यू और Jetpack Compose की तुलना की गई है

लेज़ी प्रीफ़ेच में रोके जा सकने वाले कंपोज़िशन

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

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

pausable.gif

रोकने लायक कंपोज़िशन और लेज़ी प्रीफ़ेच की सुविधा का इस्तेमाल करने से, जंक कम करने में मदद मिलती है

हमने अन्य जगहों पर भी परफ़ॉर्मेंस को ऑप्टिमाइज़ किया है. साथ ही, Modifier.onPlacedModifier.onVisibilityChanged, और अन्य मॉडिफ़ायर लागू करने की प्रोसेस को बेहतर बनाया है. हम कंपोज़ करने की सुविधा को और बेहतर बनाने के लिए काम करते रहेंगे.

नई सुविधाएं

उपयोगकर्ता को अपने साथ जोड़े रखना

Compose, अलग-अलग लाइफ़साइकल में स्टेट को सेव और मैनेज करने के लिए कई एपीआई उपलब्ध कराता है. उदाहरण के लिए, remember कंपोज़िशन के बीच स्टेट को सेव करता है. वहीं, rememberSavable/rememberSerializable का इस्तेमाल, ऐक्टिविटी या प्रोसेस को फिर से बनाने के दौरान स्टेट को सेव करने के लिए किया जाता है. retain एक नया एपीआई है, जो इन एपीआई के बीच में काम करता है. इससे आपको कॉन्फ़िगरेशन में बदलाव होने पर भी वैल्यू बनाए रखने में मदद मिलती है. हालांकि, ऐसा प्रोसेस बंद होने पर नहीं होता. retain आपकी स्थिति को क्रम से नहीं लगाता. इसलिए, आपके पास लैम्ब्डा एक्सप्रेशन, फ़्लो, और बिटमैप जैसे बड़े ऑब्जेक्ट को सेव करने का विकल्प होता है. इन्हें आसानी से क्रम से नहीं लगाया जा सकता. उदाहरण के लिए, मीडिया प्लेयर (जैसे कि ExoPlayer) को मैनेज करने के लिए, retain का इस्तेमाल किया जा सकता है. इससे यह पक्का किया जा सकता है कि कॉन्फ़िगरेशन में बदलाव होने पर, मीडिया चलाने में कोई रुकावट न आए.

@Composable

fun MediaPlayer() {

    val applicationContext = LocalContext.current.applicationContext

    val exoPlayer = retain { ExoPlayer.Builder(applicationContext).apply { ... }.build() }

    ...

}

हम AndroidDev कम्यूनिटी (खास तौर पर Circuit टीम) का शुक्रिया अदा करना चाहते हैं. इस कम्यूनिटी ने इस सुविधा को डिज़ाइन करने में हमारी मदद की है.

मटीरियल 1.4

material3 लाइब्रेरी के 1.4.0 वर्शन में, कई नए कॉम्पोनेंट और सुधार जोड़े गए हैं:

  • TextField अब TextFieldState पर आधारित एक एक्सपेरिमेंटल वर्शन उपलब्ध कराता है. यह वर्शन, टेक्स्ट की स्थिति को मैनेज करने का ज़्यादा बेहतर तरीका उपलब्ध कराता है. इसके अलावा, अब SecureTextField और OutlinedSecureTextField के नए वर्शन उपलब्ध हैं. मटीरियल Text कंपोज़ेबल अब autoSize व्यवहार के साथ काम करता है.
  • कैरसेल कॉम्पोनेंट में अब नया HorizontalCenteredHeroCarousel वैरिएंट उपलब्ध है.
  • TimePicker में अब पिकर और इनपुट मोड के बीच स्विच किया जा सकता है.
  • वर्टिकल ड्रैग हैंडल की मदद से, उपयोगकर्ता अडैप्टिव पैन का साइज़ और/या पोज़िशन बदल सकते हैं.
centered-hero-carousel.webp

हॉरिज़ॉन्टल सेंटर में मौजूद हीरो कैरसेल

ध्यान दें कि material3 लाइब्रेरी की ऐल्फ़ा रिलीज़ में, Material 3 Expressive API को डेवलप किया जा रहा है. ज़्यादा जानने के लिए, हाल ही में हुई यह बातचीत देखें:

ऐनिमेशन से जुड़ी नई सुविधाएं

हम अपने ऐनिमेशन एपीआई को बेहतर बनाते रहेंगे. साथ ही, शेयर किए गए एलिमेंट के ऐनिमेशन को पसंद के मुताबिक बनाने के लिए अपडेट भी उपलब्ध कराते रहेंगे.

डाइनैमिक शेयर किए गए एलिमेंट

डिफ़ॉल्ट रूप से, sharedElement() और sharedBounds() ऐनिमेशन, इन चीज़ों को एनिमेट करने की कोशिश करते हैं

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

शेयर किए गए एलिमेंट का ट्रांज़िशन होगा या नहीं, यह कंट्रोल करने के लिए अब SharedContentConfig को अपनी पसंद के मुताबिक बनाया जा सकता है. इसके बाद, इसे rememberSharedContentState() को पास किया जा सकता है. isEnabled प्रॉपर्टी से यह तय होता है कि शेयर किया गया एलिमेंट चालू है या नहीं.

SharedTransitionLayout {

        val transition = updateTransition(currentState)

        transition.AnimatedContent { targetState ->

            // Create the configuration that depends on state changing.

            fun animationConfig() : SharedTransitionScope.SharedContentConfig {

                return object : SharedTransitionScope.SharedContentConfig {

                    override val SharedTransitionScope.SharedContentState.isEnabled: Boolean

                        get() =

                            // determine whether to perform a shared element transition

                }

            }

}

ज़्यादा जानकारी के लिए, दस्तावेज़ देखें.

Modifier.skipToLookaheadPosition()

इस रिलीज़ में एक नया मॉडिफ़ायर, Modifier.skipToLookaheadPosition() जोड़ा गया है. यह शेयर किए गए एलिमेंट के ऐनिमेशन करते समय, कंपोज़ेबल की फ़ाइनल पोज़िशन को बनाए रखता है. इससे “दिखाएं” टाइप के ऐनिमेशन जैसे ट्रांज़िशन किए जा सकते हैं. इसे Androidify के सैंपल में देखा जा सकता है, जिसमें कैमरे को धीरे-धीरे दिखाया गया है. ज़्यादा जानकारी के लिए, यहां वीडियो से जुड़ी सलाह देखें: 

शेयर किए गए एलिमेंट के ट्रांज़िशन में शुरुआती वेलोसिटी

इस रिलीज़ में, शेयर किए गए एलिमेंट के ट्रांज़िशन के लिए नया एपीआई, prepareTransitionWithInitialVelocity जोड़ा गया है. इसकी मदद से, शेयर किए गए एलिमेंट के ट्रांज़िशन में शुरुआती वेलोसिटी (जैसे, जेस्चर से) पास की जा सकती है:

Modifier.fillMaxSize()

    .draggable2D(

        rememberDraggable2DState { offset += it },

        onDragStopped = { velocity ->

            // Set up the initial velocity for the upcoming shared element

            // transition.

            sharedContentStateForDraggableCat

                ?.prepareTransitionWithInitialVelocity(velocity)

            showDetails = false

        },

    )
fling-shared.gif

शेयर किए गए एलिमेंट का ट्रांज़िशन, जो जेस्चर से मिली शुरुआती रफ़्तार से शुरू होता है

छिपे हुए ट्रांज़िशन

EnterTransition और ExitTransition से यह तय होता है कि AnimatedVisibility/AnimatedContent कंपोज़ेबल कैसे दिखता है या गायब होता है. एक्सपेरिमेंट के तौर पर उपलब्ध नया विकल्प, कॉन्टेंट को छिपाने या धुंधला करने के लिए रंग तय करने की सुविधा देता है. उदाहरण के लिए, कॉन्टेंट पर हल्के काले रंग की लेयर को धीरे-धीरे दिखाना या छिपाना:

veil_2.gif

ऐनिमेशन वाले कॉन्टेंट को छिपाना – ऐनिमेशन के दौरान, ग्रिड वाले कॉन्टेंट पर हल्के रंग का पर्दा (या स्क्रिम) देखें

AnimatedContent(

    targetState = page,

    modifier = Modifier.fillMaxSize().weight(1f),

    transitionSpec = {

        if (targetState > initialState) {

            (slideInHorizontally { it } togetherWith

                    slideOutHorizontally { -it / 2 } + veilOut(targetColor = veilColor))

        } else {

            slideInHorizontally { -it / 2 } +

                    unveilIn(initialColor = veilColor) togetherWith slideOutHorizontally { it }

        }

    },

) { targetPage ->

    ...

}

जल्द होने वाले बदलाव

Modifier.onFirstVisible को बंद किया जा रहा है

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

जांच में कोरूटीन डिस्पैच करना

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

@get:Rule // also createAndroidComposeRule, createEmptyComposeRule

val rule = createComposeRule(effectContext = StandardTestDispatcher())

StandardTestDispatcher का इस्तेमाल करने पर, टास्क को लाइन में लगा दिया जाएगा. इसलिए, आपको composeTestRule.waitForIdle() या composeTestRule.runOnIdle() जैसे सिंक्रनाइज़ेशन मैकेनिज़्म का इस्तेमाल करना होगा. अगर आपके टेस्ट में runTest का इस्तेमाल किया जाता है, तो आपको यह पक्का करना होगा कि runTest और कंपोज़ करने के नियम के लिए, सिंक्रनाइज़ेशन के लिए एक ही StandardTestDispatcher इंस्टेंस शेयर किया गया हो.

// 1. Create a SINGLE dispatcher instance

val testDispatcher = StandardTestDispatcher()



// 2. Pass it to your Compose rule

@get:Rule

val composeRule = createComposeRule(effectContext = testDispatcher)



@Test

// 3. Pass the *SAME INSTANCE* to runTest

fun myTest() = runTest(testDispatcher) {

    composeRule.setContent { /* ... */ }

}

टूल

बेहतरीन एपीआई के लिए बेहतरीन टूल होने चाहिए. Android Studio में, Compose डेवलपर के लिए हाल ही में कई टूल जोड़े गए हैं:

इन टूल को काम करते हुए देखने के लिए, हाल ही में किया गया यह डेमो देखें:

ईमेल लिखने का आनंद लें

हम Jetpack Compose को बेहतर बनाने के लिए लगातार काम कर रहे हैं. इससे आपको ऐसे एपीआई और टूल उपलब्ध कराए जा सकेंगे जिनकी मदद से, सुंदर और बेहतर यूज़र इंटरफ़ेस (यूआई) बनाए जा सकते हैं. आपके सुझाव हमारे लिए मायने रखते हैं. इसलिए, इन बदलावों के बारे में अपने सुझाव या राय दें. इसके अलावा, यह भी बताएं कि आपको हमारे समस्या ट्रैकर में आगे क्या देखना है.

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