জেটপ্যাক কম্পোজ আর্কিটেকচারাল লেয়ারিং

এই পৃষ্ঠাটিতে জেটপ্যাক কম্পোজ গঠনকারী স্থাপত্য স্তরসমূহ এবং এর নকশার পেছনের মূল নীতিগুলোর একটি উচ্চ-স্তরের সংক্ষিপ্ত বিবরণ দেওয়া হয়েছে।

জেটপ্যাক কম্পোজ কোনো একক অখণ্ড প্রজেক্ট নয়; এটি বেশ কয়েকটি মডিউল দিয়ে তৈরি, যেগুলোকে একত্রিত করে একটি সম্পূর্ণ স্ট্যাক গঠন করা হয়। জেটপ্যাক কম্পোজ গঠনকারী বিভিন্ন মডিউলগুলো বুঝতে পারলে আপনি নিম্নলিখিত বিষয়গুলো করতে সক্ষম হবেন:

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

স্তর

Jetpack Compose-এর প্রধান স্তরগুলো হলো:

চিত্র ১. জেটপ্যাক কম্পোজ-এর প্রধান স্তরসমূহ।

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

রানটাইম
এই মডিউলটি কম্পোজ রানটাইমের মৌলিক বিষয়গুলো প্রদান করে, যেমন remember , mutableStateOf , @Composable অ্যানোটেশন এবং SideEffect । আপনার যদি শুধু কম্পোজের ট্রি ম্যানেজমেন্ট ক্ষমতার প্রয়োজন হয়, এর UI-এর নয়, তবে আপনি সরাসরি এই লেয়ারের উপর ভিত্তি করে আপনার কোড তৈরি করার কথা ভাবতে পারেন।
UI
UI লেয়ারটি একাধিক মডিউল (যেমন ui-text , ui-graphics , ui-tooling ইত্যাদি) দিয়ে গঠিত। এই মডিউলগুলো UI টুলকিটের মৌলিক বিষয়গুলো, যেমন LayoutNode , Modifier , ইনপুট হ্যান্ডলার, কাস্টম লেআউট এবং ড্রয়িং বাস্তবায়ন করে। আপনার যদি শুধু UI টুলকিটের মৌলিক ধারণাগুলোর প্রয়োজন হয়, তবে আপনি এই লেয়ারটির উপর ভিত্তি করে আপনার কাজ তৈরি করার কথা ভাবতে পারেন।
ফাউন্ডেশন
এই মডিউলটি Compose UI-এর জন্য ডিজাইন সিস্টেম নিরপেক্ষ কিছু বিল্ডিং ব্লক প্রদান করে, যেমন RowColumn , LazyColumn , নির্দিষ্ট জেসচার শনাক্তকরণ ইত্যাদি। আপনি এই ভিত্তি স্তরের উপর ভিত্তি করে আপনার নিজস্ব ডিজাইন সিস্টেম তৈরি করার কথা বিবেচনা করতে পারেন।
উপাদান
এই মডিউলটি কম্পোজ UI-এর জন্য ম্যাটেরিয়াল ডিজাইন সিস্টেমের একটি বাস্তবায়ন প্রদান করে, যার মধ্যে রয়েছে থিমিং সিস্টেম, স্টাইল করা কম্পোনেন্ট, রিপল ইন্ডিকেশন এবং আইকন। আপনার অ্যাপে ম্যাটেরিয়াল ডিজাইন ব্যবহার করার সময় এই লেয়ারটির উপর ভিত্তি করে কাজ করুন।

নকশার নীতিগুলি

জেটপ্যাক কম্পোজের একটি মূল নীতি হলো, কয়েকটি বিশাল উপাদানের পরিবর্তে এমন ছোট ও সুনির্দিষ্ট কার্যকারিতার অংশ প্রদান করা, যেগুলোকে একত্রিত (বা কম্পোজ) করা যায়। এই পদ্ধতির বেশ কিছু সুবিধা রয়েছে।

নিয়ন্ত্রণ

উচ্চ স্তরের উপাদানগুলো সাধারণত আপনার জন্য আরও বেশি কাজ করে, কিন্তু আপনার সরাসরি নিয়ন্ত্রণের সুযোগ সীমিত করে দেয়। যদি আপনার আরও বেশি নিয়ন্ত্রণের প্রয়োজন হয়, তবে আপনি নিম্ন স্তরের উপাদান ব্যবহার করার জন্য নিচে নেমে আসতে পারেন।

উদাহরণস্বরূপ, যদি আপনি কোনো কম্পোনেন্টের রঙ অ্যানিমেট করতে চান, তাহলে আপনি 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. একটি CompositionLocalProvider যা বাটনটি সক্রিয় বা নিষ্ক্রিয় হলে কন্টেন্টের আলফা পরিবর্তন করে।

  3. ProvideTextStyle ডিফল্ট টেক্সট স্টাইল নির্ধারণ করে।

  4. একটি Row বাটনের বিষয়বস্তুর জন্য ডিফল্ট লেআউট নীতি প্রদান করে।

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

তবে, যদি আপনি কোনো কম্পোনেন্টের প্যারামিটারের বাইরে গিয়ে কাস্টমাইজেশন করতে চান, তাহলে আপনি এক লেভেল নিচে নেমে কম্পোনেন্টটি ফর্ক করতে পারেন। উদাহরণস্বরূপ, ম্যাটেরিয়াল ডিজাইন অনুযায়ী বাটনের ব্যাকগ্রাউন্ড একরঙা হওয়া উচিত। আপনার যদি গ্রেডিয়েন্ট ব্যাকগ্রাউন্ডের প্রয়োজন হয়, তবে এই অপশনটি Button প্যারামিটার দ্বারা সমর্থিত নয়। এক্ষেত্রে আপনি ম্যাটেরিয়াল 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 এর উপর ভিত্তি করে তৈরি। এর ফলে, আপনি যদি উচ্চতর স্তরগুলোকে প্রতিস্থাপন করতে চান, তবে সবচেয়ে সহজে খুঁজে পাওয়া যায় এমন নামসহ আপনার নিজস্ব ইমপ্লিমেন্টেশন প্রদান করা সম্ভব হয়।

সঠিক বিমূর্ততা নির্বাচন করা

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

উদাহরণস্বরূপ, আপনি যদি আপনার কাস্টম কম্পোনেন্টে জেসচার সাপোর্ট যোগ করতে চান, তাহলে আপনি Modifier.pointerInput ব্যবহার করে এটি একেবারে শুরু থেকে তৈরি করতে পারেন, কিন্তু এর উপর ভিত্তি করে তৈরি আরও উচ্চ-স্তরের কম্পোনেন্ট রয়েছে যা একটি ভালো সূচনা হতে পারে, যেমন Modifier.draggable , Modifier.scrollable বা Modifier.swipeable

নিয়ম অনুযায়ী, সর্বোচ্চ স্তরের কম্পোনেন্টটির উপর ভিত্তি করে নির্মাণ করাকে অগ্রাধিকার দিন, যেটি আপনার প্রয়োজনীয় কার্যকারিতা প্রদান করে, যাতে এর অন্তর্ভুক্ত সর্বোত্তম অনুশীলনগুলো থেকে আপনি উপকৃত হতে পারেন।

আরও জানুন

কাস্টম ডিজাইন সিস্টেম তৈরির একটি উদাহরণের জন্য Jetsnack নমুনাটি দেখুন।

{% হুবহু %} {% endverbatim %} {% হুবহু %} {% endverbatim %}