বিড়বিড় করে: উত্তরাধিকারী উইজেটটি কীভাবে সঠিকভাবে ব্যবহার করবেন?


110

ইনহরটেড উইজেট ব্যবহার করার সঠিক উপায় কী? এখনও অবধি আমি বুঝতে পেরেছি যে এটি আপনাকে উইজেট ট্রিতে ডেটা প্রচারের সুযোগ দেয়। চূড়ান্তভাবে আপনি যদি রুট উইজেট হিসাবে রাখেন তবে এটি সমস্ত রুটের গাছে থাকা সমস্ত উইজেট থেকে অ্যাক্সেসযোগ্য হবে, যা ভাল because

বাট ইনরিটেড উইজেট অপরিবর্তনীয়, তাই আমি কীভাবে এটি আপডেট করব? এবং আরও গুরুত্বপূর্ণ কীভাবে আমার স্টেটফুলের উইজেটগুলি তাদের সাবট্রিরগুলি পুনর্নির্মাণ করতে ট্রিগার করা হয়?

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

আমি ব্রায়ান ইগানের একটি উক্তি যুক্ত করছি:

হ্যাঁ, আমি এটিকে গাছের নিচে ডেটা প্রচারের একটি উপায় হিসাবে দেখছি। আমি এপিআই ডক্স থেকে যা বিভ্রান্তি পেয়েছি তা:

"উত্তরাধিকারসূত্রে প্রাপ্ত উইজেটগুলি যখন এইভাবে উল্লেখ করা হয়, উত্তরাধিকার সূত্রে প্রাপ্ত উইজেট নিজেই রাষ্ট্র পরিবর্তন করলে গ্রাহক পুনর্নির্মাণের কারণ ঘটায়।"

আমি যখন এটি প্রথম পড়ি, তখন আমি ভেবেছিলাম:

আমি ইনহিরটেড উইজেটে কিছু ডেটা স্টাফ করতে পারি এবং এটি পরে পরিবর্তন করতে পারি। যখন সেই রূপান্তর ঘটে, তখন এটি আমার উইন্ডোজ উইজেটকে যা পেয়েছে তার উল্লেখ করে সমস্ত উইজেট পুনর্নির্মাণ করবে:

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

উত্তর:


111

সমস্যাটি আপনার উদ্ধৃতি থেকে এসেছে, যা ভুল।

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

জিনিসটি হ'ল: ইনরিটেড উইজেট হ'ল একটি সাধারণ উইজেট যা ডেটা ধারণ ছাড়া কিছুই করে না । এটির আপডেট বা যা কিছু আছে তার কোনও যুক্তি নেই। তবে, অন্যান্য উইজেটগুলির মতো এটি একটি এর সাথে যুক্ত Element। এবং কি অনুমান? এই জিনিসটি পরিবর্তনযোগ্য এবং যখনই সম্ভব তেড়ে উঠা এটিকে পুনরায় ব্যবহার করবে!

সংশোধন উদ্ধৃতিটি হবে:

ইনহারিটেড উইজেট, যখন এই উপায়ে রেফারেন্স করা হয়, যখন ইনহিরিটেড উইজেট কোনও ইনহিরিটেড এলিমেন্টের পরিবর্তনের সাথে যুক্ত হয় তখন গ্রাহক পুনর্নির্মাণের কারণ ঘটায়।

কীভাবে উইজেট / উপাদান / রেন্ডারবক্স একসাথে প্লাগ করা হয় সে সম্পর্কে দুর্দান্ত আলোচনা আছে । তবে সংক্ষেপে, এগুলি এর মতো (বামটি আপনার সাধারণ উইজেটটি বাম হয়, মাঝেরটি 'উপাদানসমূহ' এবং ডানদিকে 'রেন্ডার বাক্সগুলি থাকে'):

এখানে চিত্র বর্ণনা লিখুন

জিনিসটি হ'ল: আপনি যখন একটি নতুন উইজেট ইনস্ট্যান্ট করবেন; বিড়বিড় করা এটি পুরানোটির সাথে তুলনা করবে। এটি "উপাদান" পুনরায় ব্যবহার করুন, যা একটি রেন্ডারবক্সকে নির্দেশ করে। এবং রেন্ডারবক্স বৈশিষ্ট্যগুলি পরিবর্তন করুন।


ওকি, তবে এটি কীভাবে আমার প্রশ্নের উত্তর দেয়?

ইনহিরিটেড উইজেট ইনস্ট্যান্ট করার সময় এবং তারপরে কল করা context.inheritedWidgetOfExactType(বা MyClass.ofযা মূলত একই) যা বোঝানো হয়েছে তা হল এটি শুনবেElement আপনার সঙ্গে যুক্ত InheritedWidget। এবং যখনই এটি Elementএকটি নতুন উইজেট পায়, এটি আগের পদ্ধতির নামক কোনও উইজেটের রিফ্রেশকে বাধ্য করবে।

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

যদি আপনি সমস্ত কিছু বুঝতে পারেন তবে আপনার সমাধানটি ইতিমধ্যে অনুমান করা উচিত ছিল:

আপনার InheritedWidgetঅভ্যন্তরে এমনভাবে মোড়ানো StatefulWidgetযা একেবারে নতুন তৈরি করবেInheritedWidget যখনই কিছু পরিবর্তন হয় তখন !

আসল কোডের শেষ ফলাফলটি হ'ল:

class MyInherited extends StatefulWidget {
  static MyInheritedData of(BuildContext context) =>
      context.inheritFromWidgetOfExactType(MyInheritedData) as MyInheritedData;

  const MyInherited({Key key, this.child}) : super(key: key);

  final Widget child;

  @override
  _MyInheritedState createState() => _MyInheritedState();
}

class _MyInheritedState extends State<MyInherited> {
  String myField;

  void onMyFieldChange(String newValue) {
    setState(() {
      myField = newValue;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MyInheritedData(
      myField: myField,
      onMyFieldChange: onMyFieldChange,
      child: widget.child,
    );
  }
}

class MyInheritedData extends InheritedWidget {
  final String myField;
  final ValueChanged<String> onMyFieldChange;

  MyInheritedData({
    Key key,
    this.myField,
    this.onMyFieldChange,
    Widget child,
  }) : super(key: key, child: child);

  static MyInheritedData of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<MyInheritedData>();
  }

  @override
  bool updateShouldNotify(MyInheritedData oldWidget) {
    return oldWidget.myField != myField ||
        oldWidget.onMyFieldChange != onMyFieldChange;
  }
}

তবে নতুন ইনহারিটেড উইজেট তৈরি করে পুরো গাছটি পুনর্নির্মাণ করবেন না?

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

এবং সর্বাধিক পরিস্থিতিতে (আপনার অ্যাপ্লিকেশনটির মূল অংশে একটি উত্তরাধিকারী উইজেট থাকা), উত্তরাধিকারসূত্রে প্রাপ্ত উইজেটটি ধ্রুবক । সুতরাং কোন অপ্রয়োজনীয় পুনর্নির্মাণ।


4
তবে নতুন ইনহারিটেড উইজেট তৈরি করে পুরো গাছটি পুনর্নির্মাণ করবেন না? তাহলে কেন শ্রোতার দরকার?
থমাস

4
আপনার প্রথম মন্তব্যের জন্য, আমি আমার উত্তরের একটি তৃতীয় অংশ যুক্ত করেছি। ক্লান্তিকর হিসাবে: আমি একমত না একটি কোড স্নিপেট এটিকে মোটামুটি সহজেই তৈরি করতে পারে। এবং ডেটা অ্যাক্সেস করা কল করার মতোই সহজ MyInherited.of(context)
রামি রুসলেট 14 '4

4
আপনার আগ্রহী কিনা তা নিশ্চিত নন, তবে এই কৌশলটি দিয়ে নমুনাটি আপডেট পেয়েছেন: github.com/brianegan/flutter_architecture_sample/tree/master/… নিশ্চিতভাবে এখন কিছুটা কম নকল! যদি এই বাস্তবায়নের জন্য আপনার কাছে অন্য কোনও পরামর্শ থাকে তবে আপনার কাছে যদি কিছু মুহুর্তের অবকাশ থাকে তবে কোনও কোড পর্যালোচনা পছন্দ করবে :) তবুও এই লজিক ক্রস প্ল্যাটফর্মটি ভাগ করে নেওয়ার সর্বোত্তম উপায়টি বের করার চেষ্টা করছেন (তাড়াহুড়ো এবং ওয়েব) এবং এটি পরীক্ষাযোগ্য (তা নিশ্চিত করার জন্য) বিশেষত async স্টাফ)।
ব্রেইনেগান

4
যেহেতু updateShouldNotifyপরীক্ষাটি সর্বদা একই MyInheritedStateউদাহরণ হিসাবে উল্লেখ করা হয় , তাই কি এটি সর্বদা ফিরে আসবে না false? অবশ্যই buildপদ্ধতিটি MyInheritedStateনতুন _MyInheritedউদাহরণ তৈরি করছে , তবে dataক্ষেত্রটি সর্বদা thisকোনও উল্লেখ করে না? আমার সমস্যা হচ্ছে ... আমি কেবল হার্ড কোড দিলে কাজ করে true
সিডক

4
@ সিডক হ্যাঁ আমার খারাপ। মনে রাখবেন না যে আমি কেন এটি করেছি কারণ এটি স্পষ্টতই কাজ করবে না। সত্য এডিট করে স্থির, ধন্যবাদ।
রামি রুসলেট

20

টিএল; ডিআর

ভিতরে ভারী গণনার ব্যবহার করবেন না updateShouldNotify পদ্ধতি এবং ব্যবহারের const পরিবর্তে নতুন একটি উইজেট তৈরি


সবার আগে, আমাদের উইজেট, উপাদান এবং রেন্ডার অবজেক্টগুলি কী তা বুঝতে হবে।

  1. রেন্ডার অবজেক্টস আসলে স্ক্রিনে রেন্ডার হয়। এগুলি পরিবর্তনযোগ্য , পেইন্টিং এবং বিন্যাস যুক্তিযুক্ত। রেন্ডার ট্রি ওয়েবে ডকুমেন্ট অবজেক্ট মডেল (ডিওএম) এর সাথে খুব মিলে যায় এবং আপনি এই গাছের ডিওএম নোড হিসাবে রেন্ডার অবজেক্টের দিকে নজর দিতে পারেন
  2. উইজেট - কি রেন্ডার করা উচিত তার একটি বর্ণনা। এগুলি অপরিবর্তনীয় এবং সস্তা। সুতরাং যদি কোনও উইজেট "কী?" (ঘোষণামূলক পদ্ধতির) প্রশ্নের উত্তর দেয় তবে একটি রেন্ডার অবজেক্ট "কিভাবে?" (আবশ্যক পদ্ধতির) প্রশ্নের উত্তর দেয়। ওয়েব থেকে সাদৃশ্যটি একটি "ভার্চুয়াল ডোম"।
  3. এলিমেন্ট / বিল্ডকন্টেক্সট - উইজেট এবং রেন্ডার অবজেক্টের মধ্যে একটি প্রক্সি । এটিতে * গাছের মধ্যে একটি উইজেটের অবস্থান এবং যখন সম্পর্কিত উইজেট পরিবর্তন করা হয় তখন রেন্ডার অবজেক্টটি কীভাবে আপডেট করবেন সে সম্পর্কিত তথ্য রয়েছে।

এখন আমরা ডুব দিবেন করার জন্য প্রস্তুত হয় InheritedWidget এবং BuildContext এর পদ্ধতি inheritFromWidgetOfExactType

উদাহরণ হিসাবে আমি সুপারিশ করি আমরা ইনহিরিটড উইজেট সম্পর্কে ফ্লটারের ডকুমেন্টেশন থেকে এই উদাহরণটি বিবেচনা করব:

class FrogColor extends InheritedWidget {
  const FrogColor({
    Key key,
    @required this.color,
    @required Widget child,
  })  : assert(color != null),
        assert(child != null),
        super(key: key, child: child);

  final Color color;

  static FrogColor of(BuildContext context) {
    return context.inheritFromWidgetOfExactType(FrogColor);
  }

  @override
  bool updateShouldNotify(FrogColor old) {
    return color != old.color;
  }
}

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

যে কোনও উইজেটের মতো, ইনহেরিটেড উইজেটের সাথে সংশ্লিষ্ট এলিমেন্ট অবজেক্ট থাকে। এটি ইনহেরিটেড এলিমেন্টইনরিটেড এলিমেন্ট কল আপডেটশইড আমরা যখনই নতুন উইজেট তৈরি করি ততবার উইজেটে শট নোট করুন ( পূর্বপুরুষের কাছে কলস্টেট কল করুন)। যখন updateShouldNotify ফেরৎ সত্য মাধ্যমে InheritedElement iterates নির্ভরতা (?) এবং কল পদ্ধতি didChangeDependencies এটিতে।

ইনহরাইটেড এলিমেন্ট নির্ভরতা পায় কোথায় ? এখানে আমাদের উত্তরাধিকারী থেকে উইজেটঅফ এক্স্যাক্ট টাইপ পদ্ধতিটি দেখা উচিত ।

উত্তরাধিকারী থেকে উইজেটঅফেক্স্যাক্ট টাইপ - এই পদ্ধতিটি বিল্ডকন্টেক্সটে সংজ্ঞায়িত করা হয় এবং প্রতিটি এলিমেন্ট বিল্ডকন্টেক্সট ইন্টারফেস প্রয়োগ করে (এলিমেন্ট == বিল্ডকন্টেক্সট)। সুতরাং প্রতিটি উপাদান এই পদ্ধতি আছে।

ফ্রেম উইজেটঅফ এক্স্যাক্ট টাইপ টাইপের উত্তরের কোডটি দেখতে দিন:

final InheritedElement ancestor = _inheritedWidgets == null ? null : _inheritedWidgets[targetType];
if (ancestor != null) {
  assert(ancestor is InheritedElement);
  return inheritFromElement(ancestor, aspect: aspect);
}

এখানে আমরা টাইপ অনুসারে ম্যাপযুক্ত _inherisedWidgets এ কোনও পূর্বপুরুষের সন্ধান করার চেষ্টা করি । তাহলে পূর্বপুরুষ পাওয়া যায়, আমরা কি তবে কল inheritFromElement

উত্তরাধিকারের জন্য কোডটি থেকে :

  InheritedWidget inheritFromElement(InheritedElement ancestor, { Object aspect }) {
    assert(ancestor != null);
    _dependencies ??= HashSet<InheritedElement>();
    _dependencies.add(ancestor);
    ancestor.updateDependencies(this, aspect);
    return ancestor.widget;
  }
  1. আমরা পূর্ববর্তীকে বর্তমান উপাদানের নির্ভরতা হিসাবে যুক্ত করি (_ নির্ভরতা.এডডি (পূর্বপুরুষ))
  2. আমরা পূর্বপুরুষের নির্ভরতাগুলিতে বর্তমান উপাদান যুক্ত করি (পূর্বসূরি.অ্যাপডেট নির্ভরতা (এটি, দিক))
  3. আমরা পূর্বপুরুষের উইজেটটি উত্তরাধিকারী উইজেটঅফ্যাক্স্যাক্ট টাইপ (রিটার্ন পূর্বপুরুষ। উইজেট) এর ফলস্বরূপ প্রত্যাবর্তন করি

সুতরাং এখন আমরা জানি যে ইনহরাইটেড এলিমেন্ট তার নির্ভরতা পায়।

এখন আসুন চ্যাডডেপেন্ডেন্সি পদ্ধতিটি দেখুন method প্রতিটি উপাদানটির এই পদ্ধতি রয়েছে:

  void didChangeDependencies() {
    assert(_active); // otherwise markNeedsBuild is a no-op
    assert(_debugCheckOwnerBuildTargetExists('didChangeDependencies'));
    markNeedsBuild();
  }

আমরা দেখতে পাচ্ছি যে এই পদ্ধতিটি কেবল একটি উপাদানকে নোংরা হিসাবে চিহ্নিত করে এবং এই উপাদানটি পরবর্তী ফ্রেমে পুনর্নির্মাণ করা উচিত। পুনর্নির্মাণ মানে কোরস্প্যান্ডিং উইজেট উপাদানটিতে কল পদ্ধতি বিল্ড

তবে "আমি যখন ইনহিরিটেড উইজেটটি পুনর্নির্মাণ করি তখন পুরো উপ-গাছগুলি পুনর্নির্মাণের বিষয়ে কী?" What এখানে আমাদের মনে রাখা উচিত যে উইজেটগুলি অপরিবর্তনীয় এবং আপনি যদি নতুন উইজেট তৈরি করেন তবে ঝাঁকুনি উপ-গাছটি পুনর্নির্মাণ করবে। কিভাবে আমরা এটা ঠিক করতে পারবো?

  1. হাতে ক্যাশে উইজেটগুলি (ম্যানুয়ালি)
  2. কনস্ট ব্যবহার করুন কারণ কনস্ট কেবল মান / শ্রেণীর একমাত্র উদাহরণ তৈরি করে

4
মহান ব্যাখ্যা maksimr। বিষয়টি আমাকে সবচেয়ে বিভ্রান্ত করে তোলে হ'ল উত্তরাধিকারসূত্রে উইজেটটি প্রতিস্থাপন করা হলে পুরো উপ-গাছটি যদি পুনরায় তৈরি করা হয় তবে আপডেটের কী দরকার? শল্ডনোটাইফাই ()?
পান্ডা ওয়ার্ল্ড

3

ডক্স থেকে :

[বিল্ডকন্টেক্সটেক্সটিন.হিরিট ফ্রেম উইজেটঅফ্যাক্স্যাক্ট টাইপ] প্রদত্ত প্রকারের নিকটতম উইজেটটি প্রাপ্ত করে, যা অবশ্যই একটি কংক্রিট ইনহিরটেড উইজেট সাবক্লাসের প্রকারের হতে হবে এবং এই বিল্ডের প্রসঙ্গটি সেই উইজেটের সাথে নিবন্ধভুক্ত করে যে যখন সেই উইজেট পরিবর্তন হয় (বা সেই ধরণের নতুন উইজেট প্রবর্তিত হয়, বা উইজেট চলে যায়), এই বিল্ড প্রসঙ্গে পুনর্নির্মাণ করা হয়েছে যাতে এটি সেই উইজেট থেকে নতুন মান পেতে পারে can

এটি সাধারণত () স্ট্যাটিক পদ্ধতি থেকে স্পষ্টতই বলা হয়, যেমন থিম.ওফ।

ওপি যেমন উল্লেখ করেছে, কোনও InheritedWidgetউদাহরণ পরিবর্তন হয় না ... তবে এটি উইজেট ট্রিতে একই স্থানে একটি নতুন উদাহরণ দিয়ে প্রতিস্থাপন করা যেতে পারে। যখন এটি ঘটে তখন সম্ভব হয় যে নিবন্ধিত উইজেটগুলি পুনরায় তৈরি করা দরকার। InheritedWidget.updateShouldNotifyপদ্ধতি এই সংকল্প করে তোলে। (দেখুন: ডক্স )

সুতরাং কিভাবে একটি উদাহরণ প্রতিস্থাপন করা যেতে পারে? একটি InheritedWidgetউদাহরণ একটি দ্বারা অন্তর্ভুক্ত থাকতে পারে StatefulWidget, যা কোনও পুরানো উদাহরণটিকে নতুন উদাহরণের সাথে প্রতিস্থাপন করতে পারে।


-1

ইনরিটেড উইজেট অ্যাপ্লিকেশনটির কেন্দ্রীয়ীকৃত ডেটা পরিচালনা করে এবং এটি সন্তানের কাছে দেয়, যেমন আমরা এখানে বর্ণিত কার্টের গণনা সংরক্ষণ করতে পারি :

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.