חדשות על מוצרים

מה חדש בגרסת Jetpack פיתוח נייטיב מאפריל 2026

משך הקריאה: 5 דקות
Meghan Mehta
Developer Advocate, Android

היום, הגרסה של Jetpack פיתוח נייטיב מאפריל 2026 יציבה. הגרסה הזו כוללת את גרסה 1.11 של מודולי הליבה של Compose (ראו את מיפוי BOM המלא), כלי ניפוי באגים של רכיבים משותפים, אירועים של משטח מגע ועוד. יש לנו גם כמה ממשקי API ניסיוניים, ונשמח אם תנסו אותם ותשלחו לנו משוב.

כדי להשתמש בגרסה של היום, צריך לשדרג את גרסת Compose BOM לגרסה:

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

שינויים בגרסה Compose 1.11.0

ביצוע קורוטינות בבדיקות

אנחנו משיקים עדכון חשוב לאופן שבו כלי הכתיבה מטפל בתזמון של בדיקות. אחרי תקופת ההצטרפות שהודענו עליה ב-Compose 1.10, ממשקי ה-API לבדיקה בגרסה 2 הם עכשיו ברירת המחדל, וממשקי ה-API בגרסה 1 הוצאו משימוש. השינוי העיקרי הוא מעבר לשליחת בדיקות באמצעות ברירת המחדל החדשה. ממשקי API בגרסה 1 הסתמכו על UnconfinedTestDispatcher, שהפעיל קורוטינות באופן מיידי, אבל ממשקי API בגרסה 2 משתמשים ב-StandardTestDispatcher. המשמעות היא שכאשר מפעילים שגרת המשך (coroutine) בבדיקות, היא מתווספת לתור ולא מופעלת עד שהשעון הווירטואלי מתקדם.

כך אפשר לדמות בצורה טובה יותר את תנאי הייצור, לזהות ביעילות מצבי מירוץ ולהפוך את חבילת הבדיקות שלכם לחזקה יותר ופחות לא יציבה.

כדי לוודא שהבדיקות שלכם תואמות להתנהגות הרגילה של שגרות המשך (coroutine) וכדי למנוע בעיות תאימות בעתיד, מומלץ מאוד להעביר את חבילת הבדיקות. כדאי לעיין במדריך המקיף שלנו להעברת נתונים כדי לראות מיפויים של ממשקי API ותיקונים נפוצים.

שיפורים ברכיבים משותפים וכלים לאנימציה

הוספנו גם כמה כלים שימושיים לניפוי באגים חזותי ברכיבים משותפים וב-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, שינינו את סוג המצביע של האירועים האלה, כך שקליק וגרירה באמצעות משטח מגע לא יגרמו יותר לגלילה.

הוספנו גם תמיכה במחוות מורכבות יותר בלוח המגע, כפי שהן מזוהות על ידי הפלטפורמה החל מ-API 34, כולל החלקה עם שתי אצבעות וצביטה. רכיבים כמו Modifier.scrollable ו-Modifier.transformable מזהים אוטומטית את המחוות האלה כדי לשפר את ההתנהגות שלהם עם משטחי מגע.

השינויים האלה משפרים את ההתנהגות של משטחי מגע ברכיבים מובנים, מסירים את ההטיה המיותרת של המגע, מוסיפים תנועת התחלה אינטואיטיבית יותר של גרירה ושחרור, בחירה בלחיצה כפולה ובלחיצה משולשת בשדות טקסט ותפריטי הקשר בסגנון שולחן העבודה בשדות טקסט.

כדי לבדוק את אופן הפעולה של משטח המגע, יש ממשקי API חדשים לבדיקה עם performTrackpadInput, שמאפשרים לאמת את אופן הפעולה של האפליקציות כשמשתמשים בהן עם משטח מגע. אם יש לכם גלאי מחוות בהתאמה אישית, כדאי לאמת את ההתנהגות בכל סוגי הקלט, כולל מסכי מגע, עכברים, משטחי מגע ועטים אלקטרוניים, ולוודא שיש תמיכה בגלגלי גלילה של עכברים ובמחוות של משטחי מגע.

beforeAndAfter.webp

ברירות מחדל של מארח ההרכבה (זמן ריצה של Compose)

הוספנו את 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 הוסר כי הניווט באמצעות לחצני החיצים (D-pad) ב-TextFields מופעל עכשיו תמיד כברירת מחדל. ההתנהגות החדשה מבטיחה שאירועים של מקשי החיצים מלוח משחקים או משלט של טלוויזיה יזיזו קודם את הסמן בכיוון הנתון. המיקוד יכול לעבור לרכיב אחר רק כשהסמן מגיע לסוף הטקסט.

ממשקי API עתידיים

בגרסה הקרובה של Compose‏ 1.12.0, ‏ compileSdk ישודרג ל-compileSdk 37, ו-AGP 9 וכל האפליקציות והספריות שתלויות ב-Compose יירשו את הדרישה הזו. מומלץ להתעדכן בגרסאות האחרונות שפורסמו, כי המטרה של Compose היא לאמץ במהירות compileSdks חדשים כדי לספק גישה לתכונות האחרונות של Android. כדאי לעיין בתיעוד הזה כדי לקבל מידע נוסף על הגרסה של AGP שנתמכת ברמות שונות של API. 

ב-Compose 1.11.0, ממשקי ה-API הבאים מוצגים כ-@Experimental. נשמח לקבל מכם משוב אחרי שתנסו אותם באפליקציות שלכם. שימו לב: @Experimental APIs מסופקים לצורך הערכה וקבלת משוב בשלב מוקדם, ויכול להיות שיעברו שינויים משמעותיים או יוסרו בגרסאות עתידיות.

סגנונות (ניסוי)

אנחנו משיקים ממשק API חדש וניסיוני ל-עיצוב. ‫Style API הוא פרדיגמה חדשה להתאמה אישית של רכיבים חזותיים של רכיבים, שעד עכשיו בוצעה באמצעות משנים. הוא נועד לאפשר התאמה אישית מעמיקה ופשוטה יותר על ידי חשיפה של קבוצה סטנדרטית של מאפיינים שניתנים לעיצוב, עם עיצוב פשוט שמבוסס על מצב ומעברים עם אנימציה. ה-API החדש הזה כבר מניב שיפורים מבטיחים בביצועים. אנחנו מתכננים להשתמש בסגנונות ברכיבי Material אחרי ש-Style API יתייצב.

דוגמה בסיסית לשינוי הרקע של סגנון המצב pressed:

@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 (ניסיוני)

ה-API החדש 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 הוא API חדש ומתקדם ליצירת פריסות מורכבות ודו-ממדיות ב-Jetpack פיתוח נייטיב. הפריסות 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 (ניסיוני)

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

מתחילים לתכנת עוד היום!

יש הרבה ממשקי API חדשים ומעניינים ב-Jetpack פיתוח נייטיב, ועוד רבים בדרך, כך שזה הזמן הכי טוב לעבור ל-Jetpack פיתוח נייטיב. כמו תמיד, אנחנו מעריכים את המשוב ואת הבקשות לתכונות (במיוחד לגבי תכונות של @Experimental שנמצאות עדיין בשלבי פיתוח) – אפשר לשלוח אותם כאן. כתיבה מהנה!

נכתב על ידי:

להמשך הקריאה