שכבות ארכיטקטוניות ב-Jetpack פיתוח נייטיב

הדף הזה מספק סקירה כללית ברמה גבוהה על השכבות הארכיטקטוניות שמהן מורכב Jetpack Compose, ועל עקרונות הליבה של העיצוב.

'Jetpack פיתוח נייטיב' הוא לא פרויקט מונוליתי אחד. הוא נוצר מכמה מודולים שמרכיבים יחד סטאק שלם. ככל שתבינו את המודולים השונים שמרכיבים את 'Jetpack פיתוח נייטיב', תוכלו:

  • השתמשו ברמת ההפשטה המתאימה כדי ליצור את האפליקציה או הספרייה
  • מתי אפשר לרדת לרמה נמוכה יותר כדי לקבל יותר שליטה או התאמה אישית
  • צמצום יחסי התלות

שכבות

השכבות העיקריות של Jetpack פיתוח נייטיב הן:

איור 1. השכבות העיקריות של Jetpack פיתוח נייטיב.

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

זמן ריצה
המודול הזה מספק את העקרונות הבסיסיים של סביבת זמן הריצה של Compose, כמו remember,‏ mutableStateOf, ההערה @Composable ו-SideEffect. אם אתם צריכים רק את יכולות ניהול העץ של Compose, ולא את ממשק המשתמש שלו, כדאי לכם לפתח ישירות בשכבה הזו.
UI
שכבת ממשק המשתמש מורכבת מכמה מודולים (ui-text,‏ ui-graphics,‏ ui-tooling וכו'). המודולים האלה מטמיעים את היסודות של ערכת הכלים לבניית ממשק משתמש, כמו LayoutNode, Modifier, רכיבי handler של קלט, פריסות בהתאמה אישית ושרטוט. כדאי להשתמש בשכבה הזו אם אתם צריכים רק את המושגים הבסיסיים של ערכת כלים לממשק משתמש.
בסיס
המודול הזה מספק אבני בניין לא תלויות במערכת עיצוב לממשק המשתמש של Compose, כמו Row ו-Column, LazyColumn, זיהוי של תנועות ספציפיות וכו'. מומלץ להשתמש בשכבת הבסיס הזו כדי ליצור מערכת עיצוב משלכם.
חומר
המודול הזה מספק הטמעה של מערכת Material Design לממשק המשתמש של Compose, עם מערכת נושאים, רכיבים מעוצבים, אינדיקציות של תנודות וסמלילים. כשמשתמשים ב-Material Design באפליקציה, אפשר להשתמש בשכבה הזו.

עקרונות התכנון והעיצוב

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

בקרה

רכיבים ברמה גבוהה יותר בדרך כלל מניבים יותר תוצאות, אבל הם מגבילים את כמות הבקרה הישירה שיש לכם. אם אתם צריכים יותר שליטה, תוכלו להשתמש ברכיב ברמה נמוכה יותר.

לדוגמה, אם רוצים להוסיף אנימציה לצבע של רכיב, אפשר להשתמש ב-API animateColorAsState:

val color = animateColorAsState(if (condition) Color.Green else Color.Red)

עם זאת, אם אתם צריכים שהרכיב תמיד יתחיל באפור, אי אפשר לעשות זאת באמצעות ה-API הזה. במקום זאת, אפשר לעבור לרמה התחתונה של ה-API Animatable:

val color = remember { Animatable(Color.Gray) }
LaunchedEffect(condition) {
    color.animateTo(if (condition) Color.Green else Color.Red)
}

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

התאמה אישית

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

@Composable
fun Button(
    // …
    content: @Composable RowScope.() -> Unit
) {
    Surface(/* … */) {
        CompositionLocalProvider(/* … */) { // set LocalContentAlpha
            ProvideTextStyle(MaterialTheme.typography.button) {
                Row(
                    // …
                    content = content
                )
            }
        }
    }
}

האובייקט Button מורכב מ-4 רכיבים:

  1. חומר Surface שמספק את הרקע, הצורה, טיפול בלחיצות וכו'.

  2. CompositionLocalProvider שמשנה את גרסת האלפא של התוכן כשהלחצן מופעל או מושבת.

  3. ProvideTextStyle מגדיר את סגנון ברירת המחדל של הטקסט שבו צריך להשתמש

  4. Row מספק את מדיניות ברירת המחדל של הפריסה לתוכן הלחצן

השמטנו כמה פרמטרים והערות כדי להבהיר את המבנה, אבל הרכיב כולו מכיל רק כ-40 שורות קוד כי הוא פשוט מרכיב את 4 הרכיבים האלה כדי להטמיע את הלחצן. רכיבים כמו Button נקבעים על סמך הפרמטרים שהם חושפים, ושומרים על איזון שמאפשר התאמה אישית נפוצה מול פיצוץ של פרמטרים שעלולים להקשות על השימוש ברכיב. לדוגמה, רכיבי Material Design מציעים התאמות אישיות שצוינו במערכת Material Design, כך שקל לפעול לפי עקרונות של Material Design.

עם זאת, אם אתם רוצים לבצע התאמה אישית מעבר לפרמטרים של רכיב, תוכלו לפתוח רמה ולחבר רכיב מסוים. לדוגמה, לפי Material Design, ללחצנים צריך להיות רקע בצבע אחיד. אם אתם צריכים רקע עם שיפוע, הפרמטרים Button לא תומכים באפשרות הזו. במקרה כזה, אפשר להשתמש בהטמעה של Button ב-Material Design כמקור מידע ולפתח רכיב משלכם:

@Composable
fun GradientButton(
    // …
    background: List<Color>,
    modifier: Modifier = Modifier,
    content: @Composable RowScope.() -> Unit
) {
    Row(
        // …
        modifier = modifier
            .clickable(onClick = {})
            .background(
                Brush.horizontalGradient(background)
            )
    ) {
        CompositionLocalProvider(/* … */) { // set material LocalContentAlpha
            ProvideTextStyle(MaterialTheme.typography.button) {
                content()
            }
        }
    }
}

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

אם אתם לא רוצים להשתמש בכלל במושגי Material, למשל אם אתם יוצרים מערכת עיצוב מותאמת אישית משלכם, תוכלו להשתמש רק ברכיבים של שכבת הבסיס:

@Composable
fun BespokeButton(
    // …
    backgroundColor: Color,
    modifier: Modifier = Modifier,
    content: @Composable RowScope.() -> Unit
) {
    Row(
        // …
        modifier = modifier
            .clickable(onClick = {})
            .background(backgroundColor)
    ) {
        // No Material components used
        content()
    }
}

השמות הפשוטים ביותר שמורים לרכיבים ברמה הגבוהה ביותר ב-Jetpack Compose. לדוגמה, androidx.compose.material.Text מבוסס על androidx.compose.foundation.text.BasicText. כך תוכלו לתת לאפליקציה שלכם את השם הכי בולט שאתם רוצים להחליף, אם תרצו להחליף רמות גבוהות יותר.

בחירת רמת האבסטרקציה המתאימה

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

לדוגמה, אם רוצים להוסיף תמיכה בתנועות למרכיב מותאם אישית, אפשר ליצור אותו מאפס באמצעות Modifier.pointerInput, אבל יש רכיבים אחרים ברמה גבוהה יותר שנוצרו על סמך המרכיב הזה, שיכולים להוות נקודת התחלה טובה יותר. לדוגמה, Modifier.draggable,‏ Modifier.scrollable או Modifier.swipeable.

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

מידע נוסף

בדוגמה של Jetsnack תוכלו לראות דוגמה לבניית מערכת עיצוב בהתאמה אישית.

אין המלצות כרגע.

אפשר לנסות לחשבון Google.