Compose-এ থিঙ্কিং

Jetpack Compose হল Android-এর জন্য একটি আধুনিক ডিক্লারেটিভ UI টুলকিট। Compose আপনার অ্যাপ UI লেখা ও রক্ষণাবেক্ষণ করা সহজ করে তোলে। এটি একটি ডিক্লারেটিভ API প্রদান করে যা আপনাকে ফ্রন্টএন্ড ভিউতে ইম্পারেটিভ মিউটেশন না করেই অ্যাপ UI রেন্ডার করতে দেয়। এই পরিভাষাটি ব্যাখ্যা করার প্রয়োজন আছে, তবে আপনার অ্যাপ ডিজাইনের জন্য এর প্রভাব গুরুত্বপূর্ণ।

ডিক্লারেটিভ প্রোগ্রামিং প্যারাডাইম

ঐতিহাসিকভাবে, Android ভিউ হায়ারার্কি UI উইজেটের ট্রি হিসেবে উপস্থাপন করা হয়েছে। ব্যবহারকারীর ইন্টার‍্যাকশনের মতো বিষয়ের কারণে অ্যাপের স্ট্যাটাস পরিবর্তন হলে, বর্তমান ডেটা দেখানোর জন্য UI হায়ারার্কি আপডেট করতে হবে। UI আপডেট করার সবচেয়ে সাধারণ উপায় হল findViewById()-এর মতো ফাংশন ব্যবহার করে ট্রি ওয়াক করা এবং button.setText(String), container.addChild(View) বা img.setImageBitmap(Bitmap)-এর মতো পদ্ধতি কল করে নোড পরিবর্তন করা। এইসব পদ্ধতি উইজেটের ইন্টার্নাল স্টেট পরিবর্তন করে।

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

গত কয়েক বছর ধরে, পুরো ইন্ডাস্ট্রি ডিক্লারেটিভ UI মডেলে শিফট করতে শুরু করেছে, যা ইউজার ইন্টারফেস তৈরি ও আপডেট করা সহজ করে তোলে।

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

পুরো স্ক্রিন রিজেনারেট করার ক্ষেত্রে একটি চ্যালেঞ্জ হল যে এটি সম্ভাব্যভাবে সময়, কম্পিউটিং ক্ষমতা এবং ব্যাটারি ব্যবহারের দিক থেকে ব্যয়বহুল। এই খরচ কমাতে, Compose বুদ্ধিমত্তার সাথে বেছে নেয় যে UI-এর কোন অংশগুলি যেকোনও সময়ে আবার আঁকতে হবে। রিকম্পোজিশন-এ আলোচনা করা হয়েছে যে, আপনি কীভাবে UI কম্পোনেন্ট ডিজাইন করবেন তার উপর এর কিছু প্রভাব রয়েছে।

কম্পোজেবল ফাংশনের একটি উদাহরণ

Compose ব্যবহার করে, আপনি ডেটা গ্রহণ করে এবং UI এলিমেন্ট নির্গত করে এমন কম্পোজেবল ফাংশনের একটি সেট সংজ্ঞায়িত করে আপনার ইউজার ইন্টারফেস তৈরি করতে পারেন। উদাহরণস্বরূপ, Greeting উইজেট, যা String নেয় এবং Text উইজেট নির্গত করে যা একটি শুভেচ্ছা মেসেজ দেখায়।

একটি ফোনে Hello World টেক্সট এবং কম্পোজেবল ফাংশনের কোড দেখানো হচ্ছে যা সেই UI তৈরি করে।
ছবি ১. একটি কম্পোজেবল ফাংশন যা ডেটা পাস করে এবং স্ক্রিনে একটি টেক্সট উইজেট রেন্ডার করতে এটি ব্যবহার করে।

এই ফাংশন সম্পর্কে কয়েকটি উল্লেখযোগ্য বিষয়:

  • অ্যানোটেশন: ফাংশনটি @Composable অ্যানোটেশন দিয়ে অ্যানোটেট করা হয়েছে। সব কম্পোজেবল ফাংশনে এই অ্যানোটেশন থাকতে হবে। এই অ্যানোটেশন কম্পোজ কম্পাইলারকে জানায় যে এই ফাংশনটি ডেটাকে UI-তে রূপান্তর করার জন্য তৈরি করা হয়েছে।
  • ডেটা ইনপুট: ফাংশনটি ডেটা গ্রহণ করে। কম্পোজেবল ফাংশন প্যারামিটার গ্রহণ করতে পারে, যা অ্যাপ লজিককে UI বর্ণনা করতে দেয়। এই ক্ষেত্রে, আমাদের উইজেট String গ্রহণ করে যাতে এটি ব্যবহারকারীকে নাম ধরে অভিবাদন জানাতে পারে।
  • UI ডিসপ্লে: ফাংশনটি UI-তে টেক্সট দেখায়। এটি Text() কম্পোজেবল ফাংশন কল করার মাধ্যমে এটি করে, যা আসলে টেক্সট UI এলিমেন্ট তৈরি করে। কম্পোজেবল ফাংশন অন্যান্য কম্পোজেবল ফাংশন কল করে UI হায়ারার্কি এমিট করে।
  • কোনও রিটার্ন ভ্যালু নেই: ফাংশনটি কোনও কিছু রিটার্ন করে না। UI এমিট করে এমন Compose ফাংশন কিছু রিটার্ন করে না, কারণ সেগুলি UI উইজেট তৈরি করার পরিবর্তে টার্গেট স্ক্রিন স্টেট বর্ণনা করে।
  • প্রপার্টি: এই ফাংশন দ্রুত, আইডেমপোটেন্ট এবং সাইড-এফেক্ট মুক্ত।

    • একই আর্গুমেন্ট দিয়ে একাধিকবার কল করা হলেও ফাংশনটি একই রকম আচরণ করে এবং এটি গ্লোবাল ভেরিয়েবেল বা random()-এ কলের মতো অন্যান্য ভ্যালু ব্যবহার করে না।
    • ফাংশনটি কোনও পার্শ্বপ্রতিক্রিয়া ছাড়াই UI বর্ণনা করে, যেমন প্রপার্টি বা গ্লোবাল ভেরিয়েবেল পরিবর্তন করা।

    সাধারণত, রিকম্পোজিশন-এ আলোচনা করা কারণে, সব কম্পোজেবল ফাংশন অবশ্যই এই প্রপার্টি সহ লিখতে হবে।

ডিক্লেরেটিভ প্যারাডাইম শিফ্ট

অনেক ইম্পারেটিভ অবজেক্ট-ওরিয়েন্টেড UI টুলকিটের মাধ্যমে, আপনি উইজেটের ট্রি ইনস্ট্যান্টিয়েট করে UI শুরু করেন। আপনি প্রায়ই XML লেআউট ফাইল ইনফ্লেট করে এটি করেন। প্রতিটি উইজেট তার নিজস্ব অভ্যন্তরীণ অবস্থা বজায় রাখে এবং গেটার ও সেটার পদ্ধতি প্রকাশ করে যা অ্যাপ লজিককে উইজেটের সাথে ইন্টার‍্যাক্ট করতে দেয়।

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

Compose UI-তে ডেটার ফ্লোয়ের ইলাস্ট্রেশন, হাই-লেভেল অবজেক্ট থেকে
তার চাইল্ড পর্যন্ত।
ছবি ২. অ্যাপ লজিক টপ-লেভেল কম্পোজেবল ফাংশনে ডেটা প্রদান করে। সেই ফাংশনটি অন্যান্য কম্পোজেবলকে কল করে UI বর্ণনা করার জন্য ডেটা ব্যবহার করে এবং সেই কম্পোজেবলগুলিতে এবং হায়ারার্কির নিচের দিকে উপযুক্ত ডেটা পাস করে।

ব্যবহারকারী UI-এর সাথে ইন্টার‍্যাক্ট করলে, UI onClick-এর মতো ইভেন্ট তৈরি করে। এইসব ইভেন্ট অ্যাপ লজিককে বিজ্ঞপ্তি পাঠাবে, যা পরে অ্যাপের স্ট্যাটাস পরিবর্তন করতে পারবে। স্টেট পরিবর্তন হলে, কম্পোজেবল ফাংশনগুলি নতুন ডেটা সহ আবার কল করা হয়। এর ফলে UI এলিমেন্ট আবার আঁকা হয়--এই প্রসেসকে রিকম্পোজিশন বলা হয়।

অ্যাপ লজিক দ্বারা ম্যানেজ করা ইভেন্ট ট্রিগার করার মাধ্যমে, ইন্টার‍্যাকশনে UI এলিমেন্ট কীভাবে রেসপন্স করে তার ইলাস্ট্রেশন।
ছবি ৩. ব্যবহারকারী UI এলিমেন্টের সাথে ইন্টার‍্যাক্ট করেছেন, যার ফলে একটি ইভেন্ট ট্রিগার হয়েছে। অ্যাপ লজিক ইভেন্টে সাড়া দেয়, তারপর কম্পোজেবল ফাংশন প্রয়োজন হলে নতুন প্যারামিটার সহ অটোমেটিক আবার কল করা হয়।

ডায়নামিক কন্টেন্ট

কম্পোজেবল ফাংশন XML-এর পরিবর্তে Kotlin-এ লেখা হয় বলে, অন্য যেকোনও Kotlin কোডের মতোই সেগুলি ডায়নামিক হতে পারে। যেমন, ধরুন আপনি এমন একটি UI তৈরি করতে চান যা ব্যবহারকারীদের একটি তালিকা দেখায়:

@Composable
fun Greeting(names: List<String>) {
    for (name in names) {
        Text("Hello $name")
    }
}

এই ফাংশন নামের একটি তালিকা নেয় এবং প্রতিটি ব্যবহারকারীর জন্য একটি শুভেচ্ছা তৈরি করে। কম্পোজেবল ফাংশন বেশ জটিল হতে পারে। আপনি if স্টেটমেন্ট ব্যবহার করে সিদ্ধান্ত নিতে পারেন যে কোনও নির্দিষ্ট UI এলিমেন্ট দেখাতে চান কিনা। আপনি লুপ ব্যবহার করতে পারবেন। আপনি হেল্পার ফাংশন কল করতে পারবেন। আপনি যে ভাষায় কোড লিখছেন, সেই ভাষার সমস্ত সুবিধা ব্যবহার করতে পারবেন। এই ক্ষমতা ও নমনীয়তা Jetpack Compose-এর অন্যতম প্রধান সুবিধা।

রিকম্পোজিশন

ইম্পারেটিভ UI মডেলে, কোনও উইজেট পরিবর্তন করতে, আপনি উইজেটের ইন্টার্নাল স্টেট পরিবর্তন করতে উইজেটে একটি সেটার কল করেন। Compose-এ, আপনি নতুন ডেটা সহ কম্পোজেবল ফাংশন আবার কল করেন। এটি করলে ফাংশনটি রিকম্পোজ হয়--ফাংশন দ্বারা নির্গত উইজেটগুলি প্রয়োজন হলে নতুন ডেটা সহ আবার আঁকা হয়। Compose ফ্রেমওয়ার্ক বুদ্ধিমত্তার সাথে শুধুমাত্র পরিবর্তিত কম্পোনেন্টগুলিকেই রিকম্পোজ করতে পারে।

যেমন, এই কম্পোজেবল ফাংশনটি বিবেচনা করুন যা একটি বোতাম দেখায়:

@Composable
fun ClickCounter(clicks: Int, onClick: () -> Unit) {
    Button(onClick = onClick) {
        Text("I've been clicked $clicks times")
    }
}

বোতামে ক্লিক করা হলে, কলার clicks-এর ভ্যালু আপডেট করে। নতুন ভ্যালু দেখানোর জন্য Compose আবার Text ফাংশনের সাথে ল্যাম্বডাকে কল করে; এই প্রসেসকে রিকম্পোজিশন বলা হয়। অন্যান্য ফাংশন যা ভ্যালুর উপর নির্ভর করে না সেগুলি রিকম্পোজ করা হয় না।

আমরা যেমন আলোচনা করেছি, সম্পূর্ণ UI ট্রি আবার কম্পোজ করা কম্পিউটেশনালভাবে ব্যয়বহুল হতে পারে, যা কম্পিউটিং পাওয়ার ও ব্যাটারির আয়ু ব্যবহার করে। Compose এই ইন্টেলিজেন্ট রিকম্পোজিশন-এর মাধ্যমে এই সমস্যার সমাধান করে।

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

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

  • শেয়ার করা অবজেক্টের প্রপার্টিতে লেখা হচ্ছে
  • ViewModel-এ পর্যবেক্ষণযোগ্য আপডেট করা হচ্ছে
  • শেয়ার করা পছন্দ আপডেট করা হচ্ছে

কম্পোজেবল ফাংশন প্রতিটি ফ্রেমের মতো ঘন ঘন আবার কার্যকর করা হতে পারে, যেমন যখন একটি অ্যানিমেশন রেন্ডার করা হচ্ছে। অ্যানিমেশনের সময় জ্যাঙ্ক এড়াতে কম্পোজেবল ফাংশন দ্রুত হতে হবে। শেয়ার করা প্রেফারেন্স থেকে রিড করার মতো ব্যয়বহুল অপারেশন করতে হলে, ব্যাকগ্রাউন্ড কোরুটিনে তা করুন এবং কম্পোজেবল ফাংশনে প্যারামিটার হিসেবে ভ্যালু রেজাল্ট পাস করুন।

উদাহরণস্বরূপ, এই কোডটি SharedPreferences-এ একটি মান আপডেট করার জন্য একটি কম্পোজেবল তৈরি করে। কম্পোজেবলকে শেয়ার করা পছন্দ থেকে নিজে নিজে রিড বা রাইট করা উচিত নয়। পরিবর্তে, এই কোডটি ব্যাকগ্রাউন্ড কোরুটিনে ViewModel-এ রিড ও রাইট অপারেশন সরিয়ে দেয়। অ্যাপ লজিক বর্তমান ভ্যালু পাস করে এবং আপডেট ট্রিগার করার জন্য কলব্যাক করে।

@Composable
fun SharedPrefsToggle(
    text: String,
    value: Boolean,
    onValueChanged: (Boolean) -> Unit
) {
    Row {
        Text(text)
        Checkbox(checked = value, onCheckedChange = onValueChanged)
    }
}

Compose ব্যবহার করার সময় আপনাকে যেসব বিষয়ে সচেতন থাকতে হবে, এই ডকুমেন্টে সেইসব বিষয়ে আলোচনা করা হয়েছে:

  • রিকম্পোজিশন যতটা সম্ভব কম্পোজেবল ফাংশন এবং ল্যাম্বডা এড়িয়ে যায়।
  • রিকম্পোজিশন হল অপ্টিমিস্টিক এবং এটি বাতিল করা হতে পারে।
  • একটি কম্পোজেবল ফাংশন বেশ ঘন ঘন চালানো হতে পারে, যেমন একটি অ্যানিমেশনের প্রতিটি ফ্রেমের মতো ঘন ঘন।
  • কম্পোজেবল ফাংশন সমান্তরালভাবে এক্সিকিউট করা যেতে পারে।
  • কম্পোজেবল ফাংশন যেকোনও ক্রমে এক্সিকিউট করা যেতে পারে।

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

রিকম্পোজিশন যতটা সম্ভব এড়িয়ে যায়

আপনার UI-এর অংশগুলি ভুল হলে, Compose শুধুমাত্র আপডেট করা প্রয়োজন এমন অংশগুলি পুনরায় কম্পোজ করার জন্য যথাসাধ্য চেষ্টা করে। এর অর্থ হল, এটি UI ট্রিতে উপরে বা নিচে থাকা কোনও কম্পোজেবল এক্সিকিউট না করেই একটি Button-এর কম্পোজেবল আবার রান করার জন্য এড়িয়ে যেতে পারে।

প্রতিটি কম্পোজেবল ফাংশন এবং ল্যামডা নিজে থেকেই রিকম্পোজ হতে পারে। নিম্নলিখিত উদাহরণটি দেখায় যে কীভাবে রিকম্পোজিশন একটি তালিকা রেন্ডার করার সময় কিছু এলিমেন্ট এড়িয়ে যেতে পারে:

/**
 * Display a list of names the user can click with a header
 */
@Composable
fun NamePicker(
    header: String,
    names: List<String>,
    onNameClicked: (String) -> Unit
) {
    Column {
        // this will recompose when [header] changes, but not when [names] changes
        Text(header, style = MaterialTheme.typography.bodyLarge)
        HorizontalDivider()

        // LazyColumn is the Compose version of a RecyclerView.
        // The lambda passed to items() is similar to a RecyclerView.ViewHolder.
        LazyColumn {
            items(names) { name ->
                // When an item's [name] updates, the adapter for that item
                // will recompose. This will not recompose when [header] changes
                NamePickerItem(name, onNameClicked)
            }
        }
    }
}

/**
 * Display a single name the user can click.
 */
@Composable
private fun NamePickerItem(name: String, onClicked: (String) -> Unit) {
    Text(name, Modifier.clickable(onClick = { onClicked(name) }))
}

এই প্রতিটি স্কোপ রিকম্পোজিশনের সময় এক্সিকিউট করার একমাত্র জিনিস হতে পারে। header পরিবর্তন হলে, Compose হয়ত তার কোনও পেরেন্টকে এক্সিকিউট না করেই Column ল্যাম্বডাতে স্কিপ করতে পারে। এবং Column এক্সিকিউট করার সময়, Compose LazyColumn-এর আইটেমগুলি এড়িয়ে যাওয়ার সিদ্ধান্ত নিতে পারে, যদি names পরিবর্তন না হয়।

আবার, সব কম্পোজেবল ফাংশন বা ল্যামডা সাইড-এফেক্ট মুক্ত হতে হবে। আপনাকে কোনও সাইড-এফেক্ট পারফর্ম করতে হলে, কলব্যাক থেকে এটি ট্রিগার করুন।

রিকম্পোজিশন আশাবাদী

Compose যখনই মনে করে যে কোনও কম্পোজেবলের প্যারামিটার পরিবর্তিত হতে পারে, তখনই রিকম্পোজিশন শুরু হয়। রিকম্পোজিশন হল আশাবাদী, যার অর্থ হল প্যারামিটার আবার পরিবর্তন হওয়ার আগে রিকম্পোজিশন শেষ করার ব্যাপারে Compose আশা করে। রিকম্পোজিশন শেষ হওয়ার আগে কোনও প্যারামিটার পরিবর্তন হলে, Compose রিকম্পোজিশন বাতিল করে নতুন প্যারামিটার দিয়ে আবার শুরু করতে পারে।

রিকম্পোজিশন বাতিল করা হলে, Compose রিকম্পোজিশন থেকে UI ট্রি বাতিল করে দেয়। UI দেখানোর উপর নির্ভর করে এমন কোনও সাইড-এফেক্ট থাকলে, কম্পোজিশন বাতিল করা হলেও সাইড-এফেক্ট প্রয়োগ করা হবে। এর ফলে অ্যাপের অবস্থা সঙ্গতিহীন হয়ে যেতে পারে।

অপ্টিমিস্টিক রিকম্পোজিশন ম্যানেজ করার জন্য সব কম্পোজেবল ফাংশন ও ল্যাম্বডা আইডেমপোটেন্ট ও সাইড-এফেক্ট মুক্ত কিনা তা যাচাই করুন।

কম্পোজেবল ফাংশন প্রায়শই রান করতে পারে

কিছু ক্ষেত্রে, UI অ্যানিমেশনের প্রতিটি ফ্রেমের জন্য কম্পোজেবল ফাংশন রান করতে পারে। ফাংশনটি যদি ডিভাইস স্টোরেজ থেকে পড়ার মতো ব্যয়বহুল অপারেশন করে, তাহলে ফাংশনটি UI জ্যাঙ্ক সৃষ্টি করতে পারে।

যেমন, আপনার উইজেট ডিভাইস সেটিংস পড়ার চেষ্টা করলে, এটি সম্ভাব্যভাবে এক সেকেন্ডে শত শত বার সেই সেটিংস পড়তে পারে, যার ফলে আপনার অ্যাপের পারফর্ম্যান্সের উপর মারাত্মক প্রভাব পড়তে পারে।

কোনও কম্পোজেবল ফাংশনের ডেটার প্রয়োজন হলে, সেই ডেটার জন্য প্যারামিটার নির্ধারণ করুন। আপনি তারপরে কম্পোজিশনের বাইরে অন্য থ্রেডে ব্যয়বহুল কাজ সরাতে পারেন এবং mutableStateOf বা LiveData ব্যবহার করে প্যারামিটার হিসেবে কম্পোজেবল ফাংশনে ফলাফলের মান পাস করতে পারেন।

কম্পোজেবল ফাংশন সমান্তরালভাবে চলতে পারে

Compose, কম্পোজেবল ফাংশন সমান্তরালভাবে রান করিয়ে রিকম্পোজিশন অপ্টিমাইজ করতে পারে। এটি Compose-কে একাধিক কোর ব্যবহার করতে এবং স্ক্রিনে নেই এমন কম্পোজেবল ফাংশন কম প্রায়োরিটিতে রান করতে দেয়।

এই অপ্টিমাইজেশনের অর্থ হল, ব্যাকগ্রাউন্ড থ্রেডের পুলে কম্পোজেবল ফাংশন এক্সিকিউট হতে পারে। কোনও কম্পোজেবল ফাংশন যদি ViewModel-এ কোনও ফাংশন কল করে, তাহলে Compose একই সময়ে একাধিক থ্রেড থেকে সেই ফাংশন কল করতে পারে।

আপনার অ্যাপ্লিকেশন সঠিকভাবে কাজ করছে কিনা তা যাচাই করতে, সব কম্পোজেবল ফাংশনের কোনও সাইড-এফেক্ট থাকা উচিত নয়। পরিবর্তে, onClick-এর মতো কলব্যাক থেকে সাইড-এফেক্ট ট্রিগার করুন যা সবসময় UI থ্রেডে এক্সিকিউট হয়।

যখন একটি কম্পোজেবল ফাংশন ইনভোক করা হয়, তখন ইনভোকেশনটি কলারের থেকে আলাদা থ্রেডে ঘটতে পারে। এর অর্থ হল, কম্পোজেবল ল্যাম্বডাতে ভেরিয়েবল পরিবর্তন করে এমন কোড এড়িয়ে যেতে হবে–কারণ এই ধরনের কোড থ্রেড-সেফ নয় এবং এটি কম্পোজেবল ল্যাম্বডার একটি অননুমোদিত সাইড-এফেক্ট।

এখানে একটি উদাহরণ দেওয়া হল যেখানে কম্পোজেবল একটি তালিকা ও তার সংখ্যা দেখাচ্ছে:

@Composable
fun ListComposable(myList: List<String>) {
    Row(horizontalArrangement = Arrangement.SpaceBetween) {
        Column {
            for (item in myList) {
                Text("Item: $item")
            }
        }
        Text("Count: ${myList.size}")
    }
}

এই কোডটি সাইড-ইফেক্ট ফ্রি এবং ইনপুট লিস্টকে UI-তে ট্রান্সফর্ম করে। ছোট তালিকা দেখানোর জন্য এটি খুব ভালো কোড। তবে, ফাংশনটি যদি কোনও লোকাল ভেরিয়েবলে লেখে, তাহলে এই কোডটি থ্রেড-সেফ বা সঠিক হবে না:

@Composable
fun ListWithBug(myList: List<String>) {
    var items = 0

    Row(horizontalArrangement = Arrangement.SpaceBetween) {
        Column {
            for (item in myList) {
                Card {
                    Text("Item: $item")
                    items++ // Avoid! Side-effect of the column recomposing.
                }
            }
        }
        Text("Count: $items")
    }
}

এই উদাহরণে, প্রতিটি রিকম্পোজিশনের সাথে items পরিবর্তন করা হয়। এটি অ্যানিমেশনের প্রতিটি ফ্রেম বা তালিকা আপডেট করার সময় হতে পারে। যাই হোক, UI ভুল সংখ্যা দেখাবে। এই কারণে, এই ধরনের রাইট Compose-এ কাজ করে না; এই ধরনের রাইট নিষিদ্ধ করে, আমরা ফ্রেমওয়ার্ককে কম্পোজেবল ল্যাম্বডা এক্সিকিউট করার জন্য থ্রেড পরিবর্তন করার অনুমতি দিই।

কম্পোজেবল ফাংশন যেকোনও ক্রমে এক্সিকিউট করা যেতে পারে

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

যেমন, ধরুন আপনার কাছে একটি ট্যাব লেআউটে তিনটি স্ক্রিন আঁকার জন্য এই ধরনের কোড আছে:

@Composable
fun ButtonRow() {
    MyFancyNavigation {
        StartScreen()
        MiddleScreen()
        EndScreen()
    }
}

StartScreen, MiddleScreen ও EndScreen-কে যেকোনও ক্রমে কল করা হতে পারে। এর অর্থ হল, আপনি, উদাহরণস্বরূপ, StartScreen()-কে কিছু গ্লোবাল ভেরিয়েবেল (একটি পার্শ্ব-প্রতিক্রিয়া) সেট করতে দিতে পারবেন না এবং MiddleScreen()-কে সেই পরিবর্তনের সুবিধা নিতে দিতে পারবেন না। পরিবর্তে, এই ফাংশনগুলির প্রতিটি স্বয়ংসম্পূর্ণ হতে হবে।

আরও জানুন

Compose এবং কম্পোজেবল ফাংশন সম্পর্কে আরও জানতে, নিম্নলিখিত অতিরিক্ত রিসোর্স দেখুন।

ভিডিও