InheritedWidget হল Flutter-এর একটি বিশেষ উইজেট যা কনস্ট্রাক্টরের মাধ্যমে স্পষ্টভাবে পাস না করেই উইজেট ট্রিতে ডেটা নিচের দিকে পাঠায়। চাইল্ড উইজেটগুলি BuildContext-এর মাধ্যমে ডেটা অ্যাক্সেস করে এবং স্বয়ংক্রিয়ভাবে আপডেটের সাবস্ক্রাইব করে। InheritedWidget-এ ডেটা পরিবর্তন হলে, সমস্ত নির্ভরশীল উইজেট পুনর্নির্মিত হয়। Flutter API Reference, 2025 অনুসারে, InheritedWidget হল Theme, MediaQuery, Localizations এবং অধিকাংশ স্টেট ম্যানেজমেন্ট লাইব্রেরির ভিত্তি।
মূল পয়েন্ট
InheritedWidget হল একটি উইজেট যা তার ডেটা Widget Tree-তে সমস্ত বংশধরের জন্য উপলব্ধ করে। সাধারণ উইজেটের বিপরীতে যা শুধুমাত্র কনস্ট্রাক্টরের মাধ্যমে চাইল্ড এলিমেন্টে ডেটা পাঠায়, InheritedWidget সাবট্রির যেকোনো উইজেটকে প্যারামিটারের চেইন ছাড়াই ডেটা অ্যাক্সেস করতে দেয়। এটি “prop drilling” সমস্যার সমাধান করে — অনেক মধ্যবর্তী উইজেটের মাধ্যমে ডেটা পাঠানো যারা নিজেরা এই ডেটা ব্যবহার করে না।
Flutter-এ বেশ কয়েকটি বিল্ট-ইন InheritedWidget অন্তর্ভুক্ত রয়েছে: Theme (রঙের স্কিম এবং স্টাইল), MediaQuery (স্ক্রিন সাইজ, ওরিয়েন্টেশন, পিক্সেল ঘনত্ব), Localizations (স্থানীয়কৃত স্ট্রিং), Directionality (টেক্সট দিক), DefaultTextStyle (ডিফল্ট টেক্সট স্টাইল)। এই উইজেটগুলি MaterialApp-এর মতো রুট উইজেট দ্বারা সেট করা হয় এবং পুরো অ্যাপ্লিকেশন জুড়ে উপলব্ধ থাকে।
InheritedWidget-এর নিজস্ব কোনো স্টেট নেই — এটি কনস্ট্রাক্টরের মাধ্যমে পাঠানো ডেটা সংরক্ষণ করে। যখন InheritedWidget-এর প্যারেন্ট নতুন ডেটা নিয়ে পুনর্নির্মিত হয়, তখন পুরোনো এবং নতুন ডেটা তুলনা করার জন্য updateShouldNotify পদ্ধতি কল করা হয়। যদি পদ্ধতিটি true ফেরত দেয়, তবে সমস্ত নির্ভরশীল উইজেট পুনর্নির্মাণের জন্য চিহ্নিত হয়। এটি একটি সহজ কিন্তু কার্যকর রিঅ্যাকটিভ আপডেট মেকানিজম।
InheritedWidget-এর মাধ্যমে ডেটা পাস করার পদ্ধতি Element Tree-এর উপর ভিত্তি করে। যখন কোনো উইজেট dependOnInheritedWidgetOfExactType কল করে, তখন সংশ্লিষ্ট এলিমেন্ট InheritedElement-এর উপর একটি নির্ভরতা নিবন্ধন করে। যখন InheritedWidget পরিবর্তিত হয়, InheritedElement সমস্ত নির্ভরশীল এলিমেন্টকে জানায়, যারা পরবর্তী ফ্রেমে পুনর্নির্মিত হয়।
dependOnInheritedWidgetOfExactType পদ্ধতি শুধু ট্রিতে InheritedWidget খুঁজে পায় না — এটি বর্তমান এলিমেন্টকে নোটিফিকেশনে সাবস্ক্রাইব করে। যদি আপনি dependOn-এর পরিবর্তে findAncestorWidgetOfExactType ব্যবহার করতেন, উইজেট ডেটা পেত কিন্তু পরিবর্তন হলে পুনর্নির্মিত হতো না। এটি একটি গুরুত্বপূর্ণ পার্থক্য: dependOn একটি সাবস্ক্রিপশন, findAncestor একটি এককালীন অনুসন্ধান।
যখন কোনো উইজেট InheritedWidget অনুরোধ করে, Flutter বর্তমান এলিমেন্ট থেকে মূল পর্যন্ত Element Tree-তে উপরে ওঠে, টাইপ ম্যাচের জন্য প্রতিটি InheritedElement পরীক্ষা করে। প্রথম মিলে যাওয়া InheritedElement ফেরত দেওয়া হয়। এর অর্থ হলো ট্রিতে নিকটতম InheritedWidget-এর অগ্রাধিকার থাকে — আপনি বংশধরের কাছাকাছি InheritedWidget রেখে একটি নির্দিষ্ট স্তরে ডেটা ওভাররাইড করতে পারেন।
class ThemeData {
final Color primaryColor;
final TextTheme textTheme;
const ThemeData({required this.primaryColor, required this.textTheme});
}
class MyTheme extends InheritedWidget {
final ThemeData data;
const MyTheme({required this.data, required Widget child}) : super(child: child);
static MyTheme of(BuildContext context) {
final widget = context.dependOnInheritedWidgetOfExactType<MyTheme>();
assert(widget != null, "MyTheme not found in tree");
return widget!;
}
@override
bool updateShouldNotify(MyTheme oldWidget) => oldWidget.data != data;
}
এই উদাহরণে, MyTheme বংশধরদের ডেটা প্রদানের জন্য একটি স্ট্যাটিক of পদ্ধতি ব্যবহার করে। dependOnInheritedWidgetOfExactType পদ্ধতি একটি নির্ভরতা নিবন্ধন করে, এবং updateShouldNotify নির্ভরশীল উইজেটগুলির পুনর্নির্মাণ প্রয়োজন কিনা তা নির্ধারণ করতে পুরোনো এবং নতুন ডেটা তুলনা করে।
কাস্টম InheritedWidget তৈরিতে দুটি ধাপ অন্তর্ভুক্ত: InheritedWidget-কে প্রসারিত করে এমন একটি ক্লাস সংজ্ঞায়িত করা এবং বংশধরদের থেকে অ্যাক্সেসের জন্য একটি স্ট্যাটিক of পদ্ধতি বাস্তবায়ন করা। কনস্ট্রাক্টরের মাধ্যমে ডেটা পাঠানো হয়, এবং updateShouldNotify পদ্ধতি নির্ধারণ করে কখন নির্ভরশীল উইজেটগুলি পুনর্নির্মিত হবে।
ক্লাসটিকে InheritedWidget প্রসারিত করতে হবে এবং বাধ্যতামূলক child প্যারামিটারসহ কনস্ট্রাক্টরের মাধ্যমে ডেটা গ্রহণ করতে হবে। ডেটা যেকোনো ধরনের হতে পারে: প্রিমিটিভ, অবজেক্ট, ফাংশন। মূল নিয়ম হলো ডেটা অপরিবর্তনীয় (immutable) হতে হবে যাতে পুরোনো এবং নতুন মান নির্ভরযোগ্যভাবে তুলনা করা যায়।
স্ট্যাটিক of পদ্ধতি BuildContext নেয় এবং InheritedWidget ডেটা ফেরত দেয়। ভিতরে, এটি dependOnInheritedWidgetOfExactType কল করে, যা ট্রিতে নির্দিষ্ট টাইপের নিকটতম InheritedWidget খুঁজে পায়। যদি InheritedWidget না পাওয়া যায়, পদ্ধতিটি বাস্তবায়নের উপর নির্ভর করে একটি ব্যতিক্রম ছোড়ে বা ডিফল্ট মান ফেরত দেয়।
ডেটা অ্যাক্সেস করতে, উইজেট build পদ্ধতির ভিতরে MyWidget.of(context) কল করে। Flutter স্বয়ংক্রিয়ভাবে উইজেটটিকে আপডেটের সাবস্ক্রাইব করে। ডেটা পরিবর্তন হলে, উইজেটটি পরবর্তী ফ্রেমে পুনর্নির্মিত হয়। এটি অপ্রয়োজনীয় প্যারামিটার ছাড়াই পরিষ্কার এবং ঘোষণামূলক কোডের অনুমতি দেয়।
class UserPreferences extends InheritedWidget {
final String languageCode;
final bool darkMode;
const UserPreferences({
required this.languageCode,
required this.darkMode,
required Widget child,
}) : super(child: child);
static UserPreferences of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<UserPreferences>()!;
}
@override
bool updateShouldNotify(UserPreferences oldWidget) =>
oldWidget.languageCode != languageCode || oldWidget.darkMode != darkMode;
}
এই উদাহরণে, UserPreferences ব্যবহারকারীর সেটিংস সংরক্ষণ করে। updateShouldNotify পদ্ধতি প্রতিটি ফিল্ড পৃথকভাবে তুলনা করে, যা শুধুমাত্র একটি প্যারামিটার পরিবর্তন হলে অপ্রয়োজনীয় পুনর্নির্মাণ রোধ করে। একাধিক ফিল্ডযুক্ত নিজস্ব InheritedWidget-এর জন্য অনুরূপ পদ্ধতি ব্যবহার করুন।
updateShouldNotify হল InheritedWidget-এর মূল পদ্ধতি যা নির্ধারণ করে ডেটা পরিবর্তন সম্পর্কে নির্ভরশীল উইজেটগুলিকে জানানোর প্রয়োজন কিনা। যদি পদ্ধতিটি false ফেরত দেয়, নির্ভরশীল উইজেটগুলি পুনর্নির্মিত হয় না, এমনকি InheritedWidget নিজেও একই ডেটাসহ একটি নতুন ইনস্ট্যান্স পেলেও। এটি কর্মক্ষমতার জন্য অত্যন্ত গুরুত্বপূর্ণ।
শুধুমাত্র সেই ফিল্ডগুলি তুলনা করুন যেগুলি প্রকৃতপক্ষে পরিবর্তিত হয়েছে এবং প্রদর্শনকে প্রভাবিত করে। যদি InheritedWidget-এ 10টি ফিল্ড থাকে কিন্তু শুধুমাত্র একটি UI-কে প্রভাবিত করে, শুধুমাত্র সেই ফিল্ডটি পরীক্ষা করুন। সংগ্রহের জন্য, গভীর তুলনা বা অপরিবর্তনীয় ডেটা স্ট্রাকচার ব্যবহার করুন। List বা Map-এর জন্য == ব্যবহার করবেন না, কারণ এগুলি রেফারেন্স দ্বারা তুলনা করে।
সবচেয়ে সাধারণ ভুল হলো তুলনা ছাড়াই true ফেরত দেওয়া। এটি সমস্ত নির্ভরশীল উইজেটকে প্রতিটি প্যারেন্ট আপডেটে পুনর্নির্মিত করে, এমনকি ডেটা পরিবর্তন না হলেও। দ্বিতীয় ভুল হলো ডেটা পরিবর্তিত হলে false ফেরত দেওয়া, যা পুরোনো UI তৈরি করে। তৃতীয়টি হলো জটিল তুলনা যা প্রতিটি ফ্রেমে চলে এবং কাজ ধীর করে দেয়।
InheritedWidget এবং কলব্যাক (কনস্ট্রাক্টরের মাধ্যমে ফাংশন পাঠানো) ভিন্ন ভিন্ন সমস্যার সমাধান করে। InheritedWidget সেই ডেটার জন্য উপযুক্ত যা ট্রির বিভিন্ন স্তরে অনেক উইজেটের প্রয়োজন। কলব্যাক প্যারেন্ট থেকে নির্দিষ্ট চাইল্ডে বা তার বিপরীতে একমুখী ইভেন্ট পাঠানোর জন্য সুবিধাজনক। পছন্দটি অ্যাপ্লিকেশন আর্কিটেকচার এবং আপডেট ফ্রিকোয়েন্সির উপর নির্ভর করে।
InheritedWidget ব্যবহার করুন যখন বিভিন্ন নেস্টিং স্তরে অনেক উইজেটের ডেটা প্রয়োজন: অ্যাপ থিম, ব্যবহারকারী সেটিংস, ডিভাইস তথ্য, বর্তমান সেশন ডেটা। InheritedWidget বিশেষ করে “গ্লোবাল” ডেটার জন্য কার্যকর যা খুব কমই পরিবর্তিত হয় কিন্তু UI-এর বিভিন্ন অংশে প্রয়োজন হয়।
কলব্যাক (কলব্যাক ফাংশন) চাইল্ড উইজেট থেকে প্যারেন্টে ইভেন্ট পাঠানোর জন্য উপযুক্ত: বাটন প্রেস, তালিকা আইটেম নির্বাচন, ফর্ম জমা দেওয়া। কলব্যাক স্পষ্টভাবে নির্দেশ করে যে চাইল্ড কী কী কাজ করতে পারে এবং লুকানো নির্ভরতা তৈরি করে না। অল্প সংখ্যক স্তরে ট্রিতে ডেটা নিচে পাঠানোর জন্য, কনস্ট্রাক্টর প্যারামিটার ব্যবহার করাও সহজ।
| মাপকাঠি | InheritedWidget | কলব্যাক |
|---|---|---|
| দিক | উপর থেকে নিচে (প্যারেন্ট → বংশধর) | নিচ থেকে উপরে (চাইল্ড → প্যারেন্ট) বা সরাসরি |
| পরিধি | সম্পূর্ণ সাবট্রি | নির্দিষ্ট উইজেট |
| পুনর্নির্মাণ | ডেটা পরিবর্তনে স্বয়ংক্রিয় | ম্যানুয়াল setState প্রয়োজন |
| জটিলতা | মাঝারি (InheritedWidget ক্লাস প্রয়োজন) | কম (শুধু একটি ফাংশন) |
Provider এবং Riverpod হল InheritedWidget-এর উপর নির্মিত Flutter-এর জনপ্রিয় স্টেট ম্যানেজমেন্ট লাইব্রেরি। এগুলি এর ক্ষমতা সম্প্রসারণ করে: ChangeNotifier সমর্থন, আনমাউন্টে স্বয়ংক্রিয় নিষ্পত্তি, অলস আরম্ভ এবং জেনেরিক সহ সরলীকৃত সিনট্যাক্স যোগ করে।
Provider যেকোনো টাইপের অবজেক্ট ট্রিতে নিচে পাঠাতে InheritedWidget ব্যবহার করে। ChangeNotifierProvider ChangeNotifier-এর মাধ্যমে পরিবর্তন ট্র্যাক করে এবং notifyListeners কল করা হলে updateShouldNotify কল করে। এটি ডেভেলপারকে ম্যানুয়ালি InheritedWidget তৈরি এবং updateShouldNotify বাস্তবায়ন থেকে মুক্ত করে।
সরাসরি InheritedWidget বেশি নিয়ন্ত্রণ দেয় এবং বাহ্যিক নির্ভরতার প্রয়োজন হয় না। Provider প্রস্তুত অবকাঠামো প্রদান করে: Consumer, Selector, MultiProvider, ProxyProvider। পছন্দটি অ্যাপ্লিকেশন জটিলতার উপর নির্ভর করে। সহজ প্রকল্পের জন্য সরাসরি InheritedWidget যথেষ্ট; বড় প্রকল্পের জন্য Provider বা Riverpod বয়লারপ্লেট কোড কমায়।
// সরাসরি InheritedWidget
class UserProvider extends InheritedWidget {
final UserData userData;
const UserProvider({required this.userData, required Widget child}) : super(child: child);
static UserData of(BuildContext context) => context.dependOnInheritedWidgetOfExactType<UserProvider>()!.userData;
@override
bool updateShouldNotify(UserProvider old) => old.userData != userData;
}
// Provider সমতুল্য
return ChangeNotifierProvider<UserData>(
create: (_) => UserData(),
child: MyApp(),
);
উদাহরণে উভয় পদ্ধতি একই সমস্যা সমাধান করে — UserData ট্রিতে নিচে পাঠানো। Provider কোডের পরিমাণ কমায় কিন্তু InheritedWidget-এর কার্যপ্রণালী লুকিয়ে রাখে। সরাসরি InheritedWidget সম্পূর্ণ নিয়ন্ত্রণ এবং কী ঘটছে তা বোঝার সুযোগ দেয়, যা Flutter শেখার এবং জটিল পুনর্নির্মাণ সমস্যা ডিবাগ করার সময় বিশেষভাবে গুরুত্বপূর্ণ।
সচরাচর জিজ্ঞাসিত প্রশ্ন
InheritedWidget BuildContext-এর মাধ্যমে সমস্ত বংশধরের জন্য ডেটা উপলব্ধ করে, যেখানে সাধারণ উইজেট শুধু কনস্ট্রাক্টরের মাধ্যমে ডেটা পাঠায়। InheritedWidget বংশধরদের ডেটা আপডেটেও সাবস্ক্রাইব করে।
নির্ভরশীল উইজেটগুলি তখনই পুনর্নির্মিত হয় যখন updateShouldNotify true ফেরত দেয়। যদি পদ্ধতিটি সঠিকভাবে বাস্তবায়িত হয়, পুনর্নির্মাণ কেবল তখনই ঘটে যখন ডেটা প্রকৃতপক্ষে পরিবর্তিত হয়, প্রতিটি প্যারেন্ট পুনর্নির্মাণে নয়।
হ্যাঁ, আপনি একই ট্রিতে যেকোনো সংখ্যক InheritedWidget ব্যবহার করতে পারেন। প্রতিটি নির্দিষ্ট টাইপের ডেটা সরবরাহ করে, এবং উইজেটগুলি একসাথে একাধিক InheritedWidget থেকে ডেটা পেতে পারে।
dependOn উইজেটকে আপডেটে সাবস্ক্রাইব করে — ডেটা পরিবর্তন হলে উইজেট পুনর্নির্মিত হয়। findAncestor সাবস্ক্রিপশন ছাড়াই এককালীন অনুসন্ধান করে, এবং উইজেট ডেটা পরিবর্তন সম্পর্কে জানতে পারবে না।
সরল স্টেট (থিম, সেটিংস) এর জন্য InheritedWidget যথেষ্ট। বিজনেস লজিকযুক্ত জটিল স্টেটের জন্য Provider, Riverpod বা BLoC ব্যবহার করুন — এগুলি InheritedWidget-এর উপর নির্মিত এবং প্রয়োজনীয় অবকাঠামো যোগ করে।
সারসংক্ষেপ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন