Element Tree হল Flutter-এ একটি মধ্যবর্তী স্তর যা ডিক্লেয়ারেটিভ Widget Tree-কে ইম্পেরেটিভ RenderObject Tree-এর সাথে সংযুক্ত করে। উইজেটগুলির বিপরীতে, যা প্রতি রিবিল্ডে পুনরায় তৈরি হয়, এলিমেন্টগুলি আপডেটের মধ্যে টিকে থাকে এবং স্টেট, কী এবং লাইফসাইকেল পরিচালনা করে। Flutter API Reference, 2025 অনুসারে, কীগুলির সাথে কার্যকরভাবে কাজ করা, পারফরম্যান্স অপ্টিমাইজ করা এবং উইজেটের অপ্রত্যাশিত আচরণ ডিবাগ করার জন্য Element Tree বোঝা অপরিহার্য।
মূল বিষয়
Element Tree হল Flutter-এ একটি মধ্যবর্তী শ্রেণিবিন্যাস যা Widget Tree-র ভিত্তিতে তৈরি হয় এবং অ্যাপ্লিকেশনে উইজেটগুলির অন্তর্ভুক্তি পরিচালনা করে। প্রতিটি এলিমেন্ট ইনস্ট্যান্স ট্রির একটি উইজেটের সাথে মিলে যায় এবং এটির একটি রেফারেন্স সংরক্ষণ করে। এলিমেন্ট এবং উইজেটের মধ্যে প্রধান পার্থক্য হল এলিমেন্ট পুনর্নির্মাণের মধ্যে ট্রিতে তার অবস্থান ধরে রাখে, যেখানে উইজেট প্রতি build কলেই পুনরায় তৈরি হতে পারে।
Element Tree ছাড়া, Flutter দক্ষতার সাথে UI আপডেট করতে পারত না। যদি প্রতিটি রিবিল্ড RenderObject Tree পুনরায় তৈরি করত, তাহলে পারফরম্যান্স অগ্রহণযোগ্যভাবে কম হত। Element Tree একটি স্থিতিশীলকারী হিসাবে কাজ করে: এটি আপডেটের মধ্যে RenderObject এবং State-এর রেফারেন্স ধরে রাখে, যা Flutter-কে রেন্ডার ট্রিতে শুধুমাত্র ন্যূনতম পরিবর্তন প্রয়োগ করতে দেয়।
Flutter তিনটি প্রধান ধরনের এলিমেন্ট ব্যবহার করে: StatelessElement StatelessWidget-এর জন্য, StatefulElement StatefulWidget-এর জন্য, এবং LeafRenderObjectElement, SingleChildRenderObjectElement, MultiChildRenderObjectElement RenderObjectWidget-এর জন্য। প্রতিটি প্রকার তার উইজেট শ্রেণীর জন্য বিশেষায়িত এবং নির্ধারণ করে কীভাবে এলিমেন্ট RenderObject-এর সাথে ইন্টারঅ্যাক্ট করে।
তিন-স্তর আর্কিটেকচার Flutter-এ Widget Tree (কনফিগারেশন), Element Tree (ব্যবস্থাপনা) এবং RenderObject Tree (রেন্ডারিং) নিয়ে গঠিত। Element Tree হল সংযোগকারী লিঙ্ক: এটি Widget থেকে কনফিগারেশন পড়ে এবং RenderObject-কে কমান্ড পাঠায়। Element Tree ছাড়া, ফ্রেমওয়ার্ক ডিক্লেয়ারেটিভ বর্ণনাকে প্রকৃত রেন্ডারিংয়ের সাথে দক্ষভাবে সিঙ্ক্রোনাইজ করতে পারত না।
যখন একটি এলিমেন্ট ট্রিতে মাউন্ট করা হয়, এটি উইজেটের ধরন পরীক্ষা করে। যদি উইজেটটি RenderObjectWidget হয়, এলিমেন্টটি সংশ্লিষ্ট RenderObject তৈরি করে এবং RenderObject Tree-তে যোগ করে। যদি উইজেটটি LeafRenderObjectWidget হয়, এলিমেন্টটি একটি লিফ RenderObject তৈরি করে। StatelessWidget এবং StatefulWidget-এর জন্য, এলিমেন্টটি কেবল চাইল্ড এলিমেন্টগুলির অন্তর্ভুক্তি পরিচালনা করে।
abstract class Element {
Widget widget;
Element? parent;
List<Element>? children;
void mount(Element? parent, dynamic newSlot);
void update(Widget newWidget);
void unmount();
}
এই সরলীকৃত কোডটি Element-এর মৌলিক কাঠামো দেখায়। প্রতিটি এলিমেন্ট বর্তমান উইজেট, প্যারেন্ট এলিমেন্ট এবং চাইল্ড এলিমেন্টগুলির একটি রেফারেন্স সংরক্ষণ করে। mount, update এবং unmount পদ্ধতিগুলি এলিমেন্ট এবং তার সাথে সম্পর্কিত RenderObject-এর লাইফসাইকেল পরিচালনা করে।
প্রতিটি এলিমেন্ট Flutter-এ লাইফসাইকেলের ধাপগুলির একটি ক্রম অতিক্রম করে: তৈরি, মাউন্টিং, আপডেট এবং আনমাউন্টিং। অ্যানিমেশন, অ্যাসিঙ্ক্রোনাস অপারেশন এবং স্টেট ম্যানেজমেন্টের সাথে কাজ করার সময় অপ্রত্যাশিত আচরণ ডিবাগ করার জন্য এই ধাপগুলি বোঝা প্রয়োজন।
একটি এলিমেন্ট উইজেটের createElement পদ্ধতি কল করে তৈরি করা হয়। StatelessWidget-এর জন্য StatelessElement তৈরি হয়; StatefulWidget-এর জন্য StatefulElement তৈরি হয় (যা একটি State অবজেক্টও তৈরি করে)। RenderObjectWidget-এর জন্য সংশ্লিষ্ট RenderObjectElement তৈরি হয়। এলিমেন্ট তৈরি ঘটে যখন উইজেট প্রথমবার Widget Tree-তে উপস্থিত হয়।
মাউন্টিংয়ের সময়, এলিমেন্টটি Element Tree-তে যোগ করা হয় এবং একটি প্যারেন্ট এলিমেন্ট পায়। RenderObjectElement-এর জন্য, মাউন্টিং একটি RenderObject-ও তৈরি করে এবং এটিকে RenderObject Tree-তে অন্তর্ভুক্ত করে। যদি উইজেটটি StatefulWidget হয়, এই ধাপে State অবজেক্টের initState পদ্ধতি কল করা হয়।
যখন উইজেটটি নতুন কনফিগারেশন নিয়ে পুনর্নির্মিত হয়, এলিমেন্টটি update পদ্ধতির মাধ্যমে নতুন উইজেট পায়। এলিমেন্ট পুরানো এবং নতুন উইজেটের ধরন তুলনা করে: যদি ধরন মিলে যায়, এলিমেন্ট তার কনফিগারেশন আপডেট করে; যদি না মিলে, এলিমেন্টটি আনমাউন্ট করা হয় এবং একটি নতুন তৈরি করা হয়। একে "উইজেট পরিবর্তন" বলা হয় এবং ধরন পরিবর্তন করার সময় স্টেট হারানোর কারণ।
যখন একটি উইজেট Widget Tree থেকে সরানো হয়, এলিমেন্টের unmount পদ্ধতি কল করা হয়। এলিমেন্টটি Element Tree থেকে সরানো হয়, RenderObject RenderObject Tree থেকে সরানো হয়, এবং StatefulWidget-এর জন্য State অবজেক্টের dispose পদ্ধতি কল করা হয়। আনমাউন্ট করার পরে, এলিমেন্টটি পুনরায় ব্যবহার করা যেতে পারে যদি উইজেট আবার একই অবস্থানে উপস্থিত হয়।
কী (Key) হল এলিমেন্ট শনাক্তকরণ প্রক্রিয়া যা Flutter-কে পুরানো এবং নতুন Widget Tree থেকে উইজেট মেলাতে অনুমতি দেয় অবস্থান অনুসারে নয়, বরং একটি অনন্য শনাক্তকারী দ্বারা। কীগুলি গতিশীল তালিকার সাথে কাজ করার সময় অত্যন্ত গুরুত্বপূর্ণ যেখানে এলিমেন্টের ক্রম পরিবর্তন হতে পারে: এলিমেন্ট যোগ করা, সরানো বা পুনর্বিন্যাস করা।
কী ছাড়া, Flutter এলিমেন্টগুলিকে ট্রিতে তাদের অবস্থান অনুসারে মেলায়: পুরানো ট্রির অবস্থান 0-এর এলিমেন্টটি নতুন ট্রির অবস্থান 0-এর উইজেট দ্বারা প্রতিস্থাপিত হয়। যদি ক্রম পরিবর্তিত হয়ে থাকে, এলিমেন্টগুলি মিশ্রিত হয়ে যায় এবং স্টেট হারিয়ে যেতে পারে বা ভুল ডেটার সাথে আবদ্ধ হতে পারে। একটি কী Flutter-কে অবস্থানের পরিবর্তে শনাক্তকারী দ্বারা এলিমেন্ট অনুসন্ধান করতে বাধ্য করে।
ValueKey একটি এলিমেন্ট শনাক্ত করতে একটি সরল মান (স্ট্রিং, সংখ্যা) ব্যবহার করে। ObjectKey একটি অবজেক্ট রেফারেন্স ব্যবহার করে — উপযুক্ত যখন এলিমেন্টের কোনো স্থিতিশীল স্ট্রিং শনাক্তকারী নেই। UniqueKey প্রতিটি তৈরি করার সময় একটি অনন্য শনাক্তকারী তৈরি করে — ব্যবহৃত হয় যখন প্রতিটি উইজেট ইনস্ট্যান্স অনন্য হতে হবে।
Column(
children: items.map((item) => TodoItem(
key: ValueKey(item.id),
title: item.title,
isDone: item.isDone,
)).toList(),
)
এই উদাহরণে, item.id সহ ValueKey নিশ্চিত করে যে তালিকায় এলিমেন্টের ক্রম পরিবর্তন হলে প্রতিটি TodoItem তার স্টেট (যেমন, ইনপুট ফিল্ড ফোকাস) ধরে রাখে। কী ছাড়া, প্রথম অবস্থানের এলিমেন্টটি একই অবস্থানের পূর্ববর্তী এলিমেন্টের স্টেট পেত।
স্টেট (State) Flutter-এ উইজেটে নয়, বরং এলিমেন্টে সংরক্ষিত হয়। যখন StatefulWidget পুনর্নির্মিত হয় এবং একটি নতুন উইজেট ইনস্ট্যান্স তৈরি করে, সংশ্লিষ্ট StatefulElement পুরানো State অবজেক্টের একটি রেফারেন্স ধরে রাখে। নতুন উইজেটটি বিদ্যমান State-এর সাথে যুক্ত হয়, যা পুনর্নির্মাণের মধ্যে ডেটা সংরক্ষণ করতে দেয়।
উইজেট পুনর্নির্মাণের সময়, Flutter StatefulWidget-এর একটি নতুন ইনস্ট্যান্স তৈরি করে, কিন্তু সংশ্লিষ্ট StatefulElement Element Tree-তে থাকে। এলিমেন্টটি State-এ update পদ্ধতি কল করে, নতুন উইজেট পাস করে। এইভাবে, State অবজেক্ট এবং এর ডেটা সংরক্ষিত থাকে। স্টেট ক্ষতি শুধুমাত্র তখনই ঘটে যখন উইজেটের ধরন পরিবর্তিত হয়, কী পরিবর্তিত হয়, বা এলিমেন্ট ট্রি থেকে সরানো হয়।
InheritedElement হল একটি বিশেষ এলিমেন্ট যা চাইল্ড এলিমেন্টগুলিকে কনস্ট্রাক্টরের মাধ্যমে স্পষ্টভাবে পাস না করে প্যারেন্ট InheritedWidget থেকে ডেটা গ্রহণ করতে দেয়। যখন InheritedWidget পরিবর্তিত হয়, InheritedElement সমস্ত নির্ভরশীল এলিমেন্টকে জানায়, যা পুনর্নির্মিত হয়। এই প্রক্রিয়া Theme, MediaQuery এবং Provider-এর ভিত্তি।
Element Tree মেমরি ব্যবহার করে এবং প্রথম রেন্ডারিং গতি প্রভাবিত করে। প্রতিটি এলিমেন্ট একটি নির্দিষ্ট পরিমাণ মেমরি গ্রহণ করে: উইজেটের একটি রেফারেন্স, প্যারেন্টের একটি রেফারেন্স, চাইল্ড এলিমেন্টের একটি তালিকা, একটি স্লট এবং RenderObjectElement-এর জন্য অতিরিক্ত ফিল্ড। Element Tree অপ্টিমাইজ করা স্টার্টআপ টাইম কমায় এবং মেমরি ব্যবহার হ্রাস করে।
Flutter পুনর্নির্মাণের সময় এলিমেন্টগুলি পুনঃব্যবহার করার চেষ্টা করে। যদি নতুন কনফিগারেশনে উইজেটটির একই ধরন এবং কী থাকে, এলিমেন্টটি পুনরায় তৈরি হয় না — এটি আপডেট হয়। এটি একটি নতুন এলিমেন্ট তৈরি এবং পরবর্তী মাউন্টিংয়ের চেয়ে উল্লেখযোগ্যভাবে দ্রুত। তবে, যখন ধরন বা কী পরিবর্তিত হয়, পুরানো এলিমেন্টটি আনমাউন্ট করা হয় এবং একটি নতুন স্ক্র্যাচ থেকে তৈরি করা হয়।
RepaintBoundary RenderObject Tree-তে একটি পৃথক RenderRepaintBoundary তৈরি করে যা ট্রির একটি অংশকে বিচ্ছিন্ন করে। Element Tree স্তরে, RepaintBoundary কোনও বিশেষ এলিমেন্ট তৈরি করে না — এটি SingleChildRenderObjectElement ব্যবহার করে। পার্থক্যটি RenderObject স্তরে দেখা যায়: যখন RepaintBoundary কন্টেন্ট পরিবর্তিত হয়, শুধুমাত্র বিচ্ছিন্ন এলাকাটি পুনরায় রঙ করা হয়।
| অপারেশন | RepaintBoundary ছাড়া | RepaintBoundary সহ |
|---|---|---|
| পুনঃরঙ | সম্পূর্ণ স্ক্রিন | শুধুমাত্র বিচ্ছিন্ন এলাকা |
| সময় | ~16 ms 60 FPS-এ | ~2-5 ms |
| মেমরি | সর্বনিম্ন | + কয়েক কিলোবাইট প্রতি স্তর |
টেবিলটি যেমন দেখায়, RepaintBoundary পরিবর্তনশীল এলাকাটিকে বিচ্ছিন্ন করে পুনঃরঙের সময় উল্লেখযোগ্যভাবে হ্রাস করে। Element Tree স্তরে, এর জন্য কোনও অতিরিক্ত কনফিগারেশনের প্রয়োজন নেই — শুধু পরিবর্তনশীল উইজেটটিকে RepaintBoundary-তে মোড়ানো।
প্রায়শই জিজ্ঞাসিত প্রশ্ন
Widget Tree হল একটি কনফিগারেশন যা প্রতিটি পুনর্নির্মাণে পুনরায় তৈরি হয়। Element Tree হল একটি স্থায়ী কাঠামো যা আপডেটের মধ্যে টিকে থাকে এবং স্টেট, RenderObject এবং উইজেটের লাইফসাইকেল পরিচালনা করে।
Element Tree ছাড়া, Flutter-কে প্রতিটি স্টেট পরিবর্তনে RenderObject Tree পুনরায় তৈরি করতে হত, যা গুরুত্বপূর্ণ বিলম্ব ঘটাত। Element Tree RenderObject এবং State সংরক্ষণ করে, শুধুমাত্র ন্যূনতম পরিবর্তন প্রয়োগ করতে দেয়।
একটি এলিমেন্ট সরানো হয় যখন সংশ্লিষ্ট উইজেট Widget Tree থেকে অদৃশ্য হয়ে যায়, বা যখন উইজেটের ধরন পরিবর্তিত হয় (যেমন, Column-এর পরিবর্তে Row) বা কী পরিবর্তিত হয়। আনমাউন্ট করার সময় State-এ dispose কল করা হয়।
কীগুলি মেলানোর অ্যালগরিদম পরিবর্তন করে: অবস্থান অনুসারে এলিমেন্ট অনুসন্ধানের পরিবর্তে, Flutter কী মান অনুসারে এলিমেন্ট অনুসন্ধান করে। এটি উইজেটের ক্রম বা পরিমাণ পরিবর্তন হলে স্টেট সংরক্ষণ করতে দেয়।
হ্যাঁ, BuildContext-এর মাধ্যমে, যা একটি এলিমেন্টের বিমূর্ততা। findAncestorWidgetOfExactType এবং dependOnInheritedWidgetOfExactType পদ্ধতিগুলি Element Tree-র সাথে কাজ করে, এলিমেন্ট ট্রিতে উপরের দিকে যায়।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন