Jetpack Compose-এর আর্কিটেকচারাল লেয়ারিং

এই পৃষ্ঠায় Jetpack Compose-এর আর্কিটেকচারাল লেয়ারের হাই-লেভেল ওভারভিউ এবং এই ডিজাইনের মূল নীতি সম্পর্কে তথ্য দেওয়া হয়েছে।

Jetpack Compose কোনও একক মনোলিথিক প্রোজেক্ট নয়; এটি একাধিক মডিউল থেকে তৈরি করা হয়েছে যা একসাথে অ্যাসেম্বল করে একটি সম্পূর্ণ স্ট্যাক তৈরি করা হয়। Jetpack Compose-এর বিভিন্ন মডিউল সম্পর্কে জানলে আপনি এগুলি করতে পারবেন:

  • আপনার অ্যাপ বা লাইব্রেরি তৈরি করতে উপযুক্ত লেভেলের অ্যাবস্ট্রাকশন ব্যবহার করুন
  • আরও নিয়ন্ত্রণ বা কাস্টমাইজেশনের জন্য আপনি কখন আরও নিচের লেভেলে ‘ড্রপ ডাউন’ করতে পারবেন তা বোঝা
  • আপনার ডিপেন্ডেন্সি কমান

লেয়ার

Jetpack Compose-এর প্রধান লেয়ারগুলি হল:

ছবি ১. Jetpack Compose-এর প্রধান লেয়ার।

প্রতিটি লেয়ার নিচের লেভেলের উপর তৈরি করা হয়, যা উচ্চ লেভেলের কম্পোনেন্ট তৈরি করতে ফাংশনালিটি একত্রিত করে। প্রতিটি লেয়ার নিচের লেয়ারের পাবলিক API-এর উপর তৈরি হয় যাতে মডিউলের সীমানা যাচাই করা যায় এবং প্রয়োজন হলে আপনি যাতে যেকোনও লেয়ার পরিবর্তন করতে পারেন। আসুন, নিচ থেকে শুরু করে উপরের দিকে এই লেয়ারগুলি পরীক্ষা করে দেখি।

রানটাইম
এই মডিউল কম্পোজ রানটাইমের মৌলিক বিষয়গুলি প্রদান করে যেমন remember, mutableStateOf, the @Composable অ্যানোটেশন এবং SideEffect. আপনার যদি শুধু Compose-এর ট্রি ম্যানেজমেন্ট ক্ষমতা প্রয়োজন হয়, UI নয়, তাহলে আপনি সরাসরি এই লেয়ারের উপর তৈরি করার কথা বিবেচনা করতে পারেন।
UI
UI লেয়ার একাধিক মডিউল নিয়ে তৈরি ( ui-text, ui-graphics, ui-tooling, ইত্যাদি)। এইসব মডিউল UI টুলকিটের মূল বিষয়গুলি প্রয়োগ করে, যেমন LayoutNode, Modifier, ইনপুট হ্যান্ডলার, কাস্টম লেআউট এবং ড্রয়িং। আপনি এই লেয়ারের উপর ভিত্তি করে তৈরি করার কথা বিবেচনা করতে পারেন যদি আপনার শুধুমাত্র একটি UI টুলকিটের মৌলিক ধারণার প্রয়োজন হয়।
Foundation
এই মডিউল Compose UI-এর জন্য ডিজাইন সিস্টেম অ্যাগনস্টিক বিল্ডিং ব্লক প্রদান করে, যেমন Row এবং 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-এর প্রয়োগ বিবেচনা করুন:

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

Button ৪টি উপাদান নিয়ে গঠিত:

  1. একটি মেটেরিয়াল Surface ব্যাকগ্রাউন্ড, আকার, ক্লিক হ্যান্ডলিং ইত্যাদি প্রদান করে।

  2. A CompositionLocalProvider যা বোতাম চালু বা বন্ধ করা হলে কন্টেন্টের আলফা পরিবর্তন করে

  3. ProvideTextStyle ব্যবহার করার জন্য ডিফল্ট টেক্সট স্টাইল সেট করে

  4. Row বোতামের কন্টেন্টের জন্য ডিফল্ট লেআউট নীতি প্রদান করে

আমরা স্ট্রাকচারটি আরও স্পষ্ট করার জন্য কিছু প্যারামিটার এবং কমেন্ট বাদ দিয়েছি, কিন্তু সম্পূর্ণ কম্পোনেন্টটি মাত্র ৪০ লাইনের কোড কারণ এটি বোতামটি প্রয়োগ করার জন্য এই ৪টি কম্পোনেন্টকে একত্রিত করে। Button-এর মতো কম্পোনেন্ট কোন প্যারামিটার দেখাবে সেই ব্যাপারে মতামত দেয়, সাধারণ কাস্টমাইজেশন চালু করার সাথে সাথে প্যারামিটারের বিস্ফোরণকে ব্যালেন্স করে, যা কম্পোনেন্ট ব্যবহার করা কঠিন করে তুলতে পারে। যেমন, মেটেরিয়াল কম্পোনেন্ট, মেটেরিয়াল ডিজাইন সিস্টেমে নির্দিষ্ট করা কাস্টমাইজেশন অফার করে, যা মেটেরিয়াল ডিজাইন নীতি অনুসরণ করা সহজ করে তোলে।

তবে, আপনি যদি কোনও কম্পোনেন্টের প্যারামিটারের বাইরে কাস্টমাইজ করতে চান, তাহলে আপনি একটি লেভেল "ড্রপ ডাউন" করতে এবং একটি কম্পোনেন্ট ফর্ক করতে পারেন। যেমন, মেটেরিয়াল ডিজাইন অনুযায়ী বোতামের ব্যাকগ্রাউন্ডে সলিড রঙ থাকতে হবে। আপনার গ্রেডিয়েন্ট ব্যাকগ্রাউন্ডের প্রয়োজন হলে, এই বিকল্পটি Button প্যারামিটারে কাজ করে না। এই ক্ষেত্রে আপনি রেফারেন্স হিসেবে Material Button ইমপ্লিমেন্টেশন ব্যবহার করতে এবং আপনার নিজস্ব কম্পোনেন্ট তৈরি করতে পারেন:

@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()
            }
        }
    }
}

উপরের ইমপ্লিমেন্টেশন, মেটেরিয়াল লেয়ার থেকে কম্পোনেন্ট ব্যবহার করা চালিয়ে যায়, যেমন মেটেরিয়ালের বর্তমান কন্টেন্ট আলফা এবং বর্তমান টেক্সট স্টাইলের ধারণা। তবে, এটি মেটেরিয়াল 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 স্যাম্পেল দেখুন।