لایه بندی معماری Jetpack Compose

این صفحه یک نمای کلی در سطح بالایی از لایه های معماری تشکیل دهنده Jetpack Compose و اصول اصلی که این طراحی را تشکیل می دهند ارائه می دهد.

Jetpack Compose یک پروژه یکپارچه واحد نیست. از تعدادی ماژول ساخته شده است که با هم مونتاژ می شوند تا یک پشته کامل را تشکیل دهند. درک ماژول های مختلف سازنده Jetpack Compose شما را قادر می سازد:

  • از سطح مناسب انتزاع برای ساختن اپلیکیشن یا کتابخانه خود استفاده کنید
  • درک کنید که چه زمانی می‌توانید برای کنترل یا سفارشی‌سازی بیشتر، به سطح پایین‌تری رها شوید
  • وابستگی های خود را به حداقل برسانید

لایه ها

لایه های اصلی Jetpack Compose عبارتند از:

شکل 1. لایه های اصلی Jetpack Compose.

هر لایه بر روی سطوح پایین تر ساخته شده است و عملکرد را برای ایجاد اجزای سطح بالاتر ترکیب می کند. هر لایه بر روی APIهای عمومی لایه‌های پایین‌تر ساخته می‌شود تا مرزهای ماژول را تأیید کند و شما را قادر می‌سازد تا هر لایه را در صورت نیاز جایگزین کنید. بیایید این لایه ها را از پایین به بالا بررسی کنیم.

زمان اجرا
این ماژول اصول زمان اجرا Compose مانند remember ، mutableStateOf ، حاشیه نویسی @Composable و SideEffect را ارائه می دهد. اگر فقط به توانایی های مدیریت درخت Compose نیاز دارید، نه UI آن، می توانید مستقیماً روی این لایه ایجاد کنید.
UI
لایه UI از چندین ماژول ( ui-text ، ui-graphics ، ui-tooling و غیره) تشکیل شده است. این ماژول‌ها اصول جعبه ابزار UI، مانند LayoutNode ، Modifier ، کنترل‌کننده‌های ورودی، طرح‌بندی‌های سفارشی و طراحی را پیاده‌سازی می‌کنند. اگر فقط به مفاهیم اساسی یک جعبه ابزار UI نیاز دارید، می‌توانید روی این لایه بسازید.
بنیاد
این ماژول بلوک‌های ساختمانی آگنوستیک سیستم طراحی را برای Compose UI فراهم می‌کند، مانند Row and Column ، LazyColumn ، تشخیص حرکات خاص، و غیره. ممکن است برای ایجاد سیستم طراحی خود، روی لایه پایه ایجاد کنید.
مواد
این ماژول پیاده‌سازی سیستم طراحی متریال را برای Compose UI ارائه می‌کند که یک سیستم موضوعی، اجزای سبک، نشانه‌های موج دار، نمادها را ارائه می‌دهد. هنگام استفاده از طراحی متریال در برنامه خود، بر روی این لایه بسازید.

اصول طراحی

یک اصل راهنما برای Jetpack Compose این است که به جای چند جزء یکپارچه، قطعات کوچک و متمرکزی از عملکرد ارائه دهد که بتوان آنها را با هم مونتاژ کرد (یا ترکیب کرد). این رویکرد دارای تعدادی مزیت است.

کنترل کنید

اجزای سطح بالاتر تمایل دارند کارهای بیشتری برای شما انجام دهند، اما میزان کنترل مستقیمی که دارید را محدود می کنند. اگر به کنترل بیشتری نیاز دارید، می‌توانید برای استفاده از یک جزء سطح پایین‌تر، «کم کردن» را انجام دهید.

به عنوان مثال، اگر می خواهید رنگ یک جزء را متحرک کنید، ممکن است از animateColorAsState API استفاده کنید:

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

با این حال، اگر به این کامپوننت نیاز دارید که همیشه خاکستری شروع شود، نمی‌توانید با این API این کار را انجام دهید. درعوض، می‌توانید برای استفاده از Animatable API سطح پایین‌تر پایین بیایید:

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

سطح بالاتر animateColorAsState API خود بر روی سطح پایین تر Animatable API ساخته شده است. استفاده از API سطح پایین تر پیچیده تر است اما کنترل بیشتری را ارائه می دهد. سطحی از انتزاع را انتخاب کنید که به بهترین وجه با نیازهای شما مطابقت دارد.

سفارشی سازی

مونتاژ اجزای سطح بالاتر از بلوک های ساختمانی کوچکتر، سفارشی کردن اجزا را در صورت نیاز بسیار آسان تر می کند. به عنوان مثال، اجرای Button ارائه شده توسط لایه Material را در نظر بگیرید:

@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 مشخص می کند که دکمه ها باید یک پس زمینه رنگی ثابت داشته باشند. اگر به پس زمینه گرادیان نیاز دارید، این گزینه توسط پارامترهای Button پشتیبانی نمی شود. در این مورد می توانید از اجرای Button Material به عنوان مرجع استفاده کنید و جزء خود را بسازید:

@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، مانند مفاهیم آلفای محتوای فعلی و سبک متن فعلی ادامه می دهد. با این حال، متریال Surface با یک Row جایگزین می کند و آن را برای رسیدن به ظاهر مورد نظر سبک می کند.

اگر اصلاً نمی‌خواهید از مفاهیم متریال استفاده کنید، برای مثال اگر سیستم طراحی سفارشی خود را بسازید، می‌توانید صرفاً از اجزای لایه پایه استفاده کنید:

@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 مراجعه کنید.

{% کلمه به کلمه %} {% آخر کلمه %} {% کلمه به کلمه %} {% آخر کلمه %}