রচনার মধ্যে চিন্তা

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

ঘোষণামূলক প্রোগ্রামিং দৃষ্টান্ত

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

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

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

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

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

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

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

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

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

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

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

ঘোষণামূলক দৃষ্টান্তের পরিবর্তন

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

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

একটি কম্পোজ 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")
    }
}

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

পুনর্গঠন

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

উদাহরণস্বরূপ, এই কম্পোজেবল ফাংশনটি বিবেচনা করুন যা একটি বোতাম প্রদর্শন করে:

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

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

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

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

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

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

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

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

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

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

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

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

পুনর্গঠন যতটা সম্ভব এড়িয়ে যায়

যখন আপনার 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 lambda-তে চলে যেতে পারে। এবং Column এক্সিকিউট করার সময়, names পরিবর্তন না হলে Compose LazyColumn এর আইটেমগুলি এড়িয়ে যেতে পারে।

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

পুনর্গঠন আশাবাদী

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

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

যাচাই করুন যে সমস্ত কম্পোজেবল ফাংশন এবং ল্যাম্বডাস আশাবাদী পুনর্গঠন পরিচালনা করার জন্য অযোগ্য এবং পার্শ্ব প্রতিক্রিয়ামুক্ত।

কম্পোজেবল ফাংশনগুলি বেশ ঘন ঘন চলতে পারে

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

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

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

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

কম্পোজ সমান্তরালভাবে কম্পোজেবল ফাংশন চালানোর মাধ্যমে রিকম্পোজিশনের অপটিমাইজেশন করতে পারে। এর ফলে কম্পোজ একাধিক কোরের সুবিধা নিতে পারবে এবং স্ক্রিনে থাকা কম্পোজেবল ফাংশনগুলিকে কম অগ্রাধিকারে চালাতে পারবে।

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

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

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

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

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

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

আরও জানুন

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

ভিডিও

{% অক্ষরে অক্ষরে %} {% এন্ডভারব্যাটিম %} {% অক্ষরে অক্ষরে %} {% এন্ডভারব্যাটিম %}