Skip to content

Latest commit

 

History

History
725 lines (511 loc) · 40.8 KB

README.md

File metadata and controls

725 lines (511 loc) · 40.8 KB

English | Português | 简体中文 | Español | 한국어 | বাংলা | 日本語

Build Status codecov Discord

এটি InheritedWidget এর চারপাশে একটি মোড়ক যা ব্যবহার করে আপনি এগুলাকে আরো সহজ এবং পুনঃব্যবহারযোগ্য করতে পারবেন।

ম্যানুয়ালি InheritedWidget লেখার পরিবর্তে provider ব্যবহার করে, আপনি পাবেন:

  • সরলীকৃতভাবে রিসোর্স নিষ্পত্তি/ডিস্পোস
  • লেজি-লোডিং
  • প্রতিবার একটি নতুন ক্লাস তৈরি করার জন্য একটি ব্যাপকভাবে হ্রাস করা বয়লারপ্লেট
  • devtool-এর সাথে বন্ধুত্বপূর্ণ - প্রভাইডার ব্যবহার করে, আপনার এপ্লিকেশন এর স্টেট Flutter devtool-এ দৃশ্যমান হবে
  • এই InheritedWidgetগুলি ব্যবহার করার একটি সাধারণ উপায় (দেখুন Provider.of/Consumer/Selector)
  • লিসেনিং পদ্ধতির সাথে ক্লাসের জন্য বর্ধিত মাপযোগ্যতা যা জটিলতায় দ্রুত বৃদ্ধি পায় (যেমন ChangeNotifier, যা নোটিফিকেশন পাঠানোর জন্য O(N)।

একটি `প্রভাইডার' সম্পর্কে আরও পড়তে, এটির ডকুমেন্টেশন দেখুন।

আর দেখুনঃ

4.x.x থেকে 5.0.0-nullsafety-এ মাইগ্রেশন

  • FutureProvider এবং StreamProvider উভয়ের জন্য initialData এখন প্রয়োজন।

মাইগ্রেট করতে, আগে যা হতোঃ

FutureProvider<int>(
  create: (context) => Future.value(42),
  child: MyApp(),
)

Widget build(BuildContext context) {
  final value = context.watch<int>();
  return Text('$value');
}

আর এখনঃ

FutureProvider<int?>(
  initialValue: null,
  create: (context) => Future.value(42),
  child: MyApp(),
)

Widget build(BuildContext context) {
  // খেয়াল রাখবেন যেন "?" দেওয়া হয়, যেমনঃ context.watch<int?>();
  return Text('$value');
}
  • ValueListenableProvider রিমোভ করে দেওয়া হয়েছে

    মাইগ্রেট করতে, আপনি Provider ব্যবহার করতে পারেন ValueListenableBuilder এর সাথে যোগ করেঃ

    ValueListenableBuilder<int>(
      valueListenable: myValueListenable,
      builder: (context, value, _) {
        return Provider<int>.value(
          value: value,
          child: MyApp(),
        );
      }
    )

ব্যবহার

একটি ভ্যালু এক্সপোস করা

একটি নতুন অবজেক্ট এর ইন্সট্যান্স এক্সপোস করা

প্রভাইডাররা আপনাকে শুধুমাত্র একটি ভ্যালু প্রকাশ করতে দেয় না, বরং এটি তৈরি করতে, শুনতে এবং নিষ্পত্তি করতে দেয়।

একটি নতুন তৈরি অবজেক্ট এক্সপোস করতে, একটি প্রভাইডারের ডিফল্ট কনস্ট্রাক্টর ব্যবহার করুন।

আপনি যদি কোনো অবজেক্ট তৈরি করতে চান তাহলে .value কনস্ট্রাক্টর ব্যবহার করবেন না, অথবা অন্যথায় আপনার অযাচিত পার্শ্বপ্রতিক্রিয়া হতে পারে।

এই StackOverflow উত্তরটি দেখুন যা ব্যাখ্যা করে কেন ভ্যালু তৈরি করতে .value কনস্ট্রাক্টর ব্যবহার করা অনাকাঙ্ক্ষিত

  • create এর মধ্যে অবজেক্ট তৈরি করুনঃ
Provider(
  create: (_) => MyModel(),
  child: ...
)
  • অবজেক্ট তৈরিতে Provider.value কখনোই ব্যবহার করবেন না।
ChangeNotifierProvider.value(
  value: MyModel(),
  child: ...
)
  • সময়ের সাথে পরিবর্তন হতে পারে এমন ভেরিয়েবল থেকে আপনার অবজেক্ট তৈরি করবেন না।

    এমন পরিস্থিতিতে, ভ্যালু পরিবর্তন হলে আপনার অবজেক্ট কখনই আপডেট হবে না।

int count;

Provider(
  create: (_) => MyModel(count),
  child: ...
)

আপনি যদি ভেরিয়েবলগুলি পাস করতে চান যা সময়ের সাথে সাথে আপনার অবজেক্টে পরিবর্তন করতে পারে, ProxyProvider ব্যবহার করে বিবেচনা করুনঃ

int count;

ProxyProvider0(
  update: (_, __) => MyModel(count),
  child: ...
)

নোটঃ

একটি প্রভাইডারের create/update কলব্যাক ব্যবহার করার সময়, এটি লক্ষণীয় যে এই কলব্যাকটিকে ডিফল্টরূপে লেজি/অলসভাবে কল করা হয়।

এর মানে হল অন্তত একবার ভ্যালু অনুরোধ না করা পর্যন্ত, create/update কলব্যাক কল করা হবে না।

আপনি যদি lazy প্যারামিটার ব্যবহার করে কিছু যুক্তি প্রাক-গণনা করতে চান তবে এই আচরণটি অক্ষম করা যেতে পারেঃ

MyProvider(
  create: (_) => Something(),
  lazy: false,
)

একটি বিদ্যমান বস্তুর ইন্সট্যান্স পুনরায় ব্যবহার করা হচ্ছেঃ

আপনার যদি ইতিমধ্যেই একটি বস্তুর ইন্সট্যান্স থাকে এবং আপনি এটি প্রকাশ করতে চান, তাহলে একটি প্রদানকারীর .value কনস্ট্রাক্টর ব্যবহার করা ভাল হবে৷

এটি করতে ব্যর্থ হলে আপনার অবজেক্টকে dispose পদ্ধতি কল হতে পারে যখন এটি এখনও ব্যবহার করা হয়।

  • একটি বিদ্যমান ChangeNotifier প্রদান করতে ChangeNotifierProvider.value ব্যবহার করুন।
MyChangeNotifier variable;

ChangeNotifierProvider.value(
  value: variable,
  child: ...
)
  • ডিফল্ট কনস্ট্রাক্টর ব্যবহার করে একটি বিদ্যমান ChangeNotifier পুনরায় ব্যবহার করবেন না
MyChangeNotifier variable;

ChangeNotifierProvider(
  create: (_) => variable,
  child: ...
)

একটি ভ্যালু রিড করা

একটি ভ্যালু রিড করার সবচেয়ে সহজ উপায় হল [BuildContext] এ এক্সটেনশন পদ্ধতি ব্যবহার করেঃ

  • context.watch<T>(),যা উইজেট পরিবর্তনগুলি রিড করতে সাহায্য করে T এর মধ্যে
  • context.read<T>(), যেটি T রিটার্ন করে লিসেন করা ছাড়া
  • context.select<T, R>(R cb(T value)), যা একটি উইজেটকে T এর একটি ছোট অংশ লিসেন করতে দেয়।

অনেকে স্ট্যাটিক পদ্ধতি ব্যবহার করতে পারে Provider.of<T>(context), যা watch এর মতোই আচরণ করবে। যখন listen প্যারামিটার false তে সেট করা হয় (যেমন Provider.of<T>(context, listen: false)), তখন এটি read এর মতোই আচরণ করবে।

এটা লক্ষণীয় যে context.read<T>() কোনো উইজেট পুনর্নির্মাণ করবে না যখন ভ্যালু পরিবর্তন হবে এবং এটিকে StatelessWidget.build/State.build-এর মধ্যে কল করা যাবে না। অন্যদিকে, এটিকে এই মেথডগুলির বাইরে অবাধে কল করা যেতে পারে।

এই মেথডগুলি BuildContext পাস করা উইজেট থেকে শুরু করে উইজেট ট্রিতে দেখাবে এবং পাওয়া T প্রকারের নিকটতম ভেরিয়েবল রিটার্ন দেবে (অথবা কিছু না পাওয়া গেলে throw দেওয়া হবে)।

এই অপারেশন হল O(1)। এটি উইজেট ট্রিতে নড়াচড়ার সাথে জড়িত নয়।

একটি ভ্যালু প্রকাশ করা এর প্রথম উদাহরণের সাথে মিলিত হয়ে, এই উইজেটটি একটি উন্মুক্ত String রিড করবে এবং "Hello World." রেন্ডার করবে।

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text(
      // আপনি `watch` প্রাপ্ত করতে চান অবজেক্ট টাইপ 
      // পাস করতে ভুলবেন না!
      context.watch<String>(),
    );
  }
}

বিকল্পভাবে, এই পদ্ধতিগুলি ব্যবহার করার পরিবর্তে, আমরা Consumer এবং Selector ব্যবহার করতে পারি।

এগুলি পারফরমেন্স অপ্টিমাইজেশানের জন্য বা যখন প্রভাইডারের একটি BuildContext উত্তরসূরি পাওয়া কঠিন হয় তার জন্য উপযোগী হতে পারে।

সচারাচর জিজ্ঞাসা দেখুন অথবা Consumer এর ডকুমেন্টেশন এবং Selector আরও তথ্যের জন্য.

ঐচ্ছিকভাবে একটি প্রভাইডারের উপর নির্ভর করা

কখনও কখনও, আমরা এমন ক্ষেত্র সমর্থন করতে চাই যেখানে কোনও প্রভাইডার নেই। একটি উদাহরণ হল পুনঃব্যবহারযোগ্য উইজেটগুলির জন্য যা একটি প্রভাইডারের বাইরে সহ বিভিন্ন স্থানে ব্যবহার করা যেতে পারে।

এটি করতে, context.watch/context.read কল করার সময়, জেনেরিক টাইপটিকে বাতিলযোগ্য করুন। এর পরিবর্তে যেমনঃ

context.watch<Model>()

যেটি একটি ProviderNotFoundException নিক্ষেপ করবে যদি কোনো মিল প্রভাইডার পাওয়া না যায়, তাহলে এটি করুনঃ

context.watch<Model?>()

যা একটি ম্যাচিং প্রভাইডার প্রাপ্ত করার চেষ্টা করবে. কিন্তু কোনোটি না পাওয়া গেলে, নিক্ষেপের পরিবর্তে null ফেরত দেওয়া হবে।

MultiProvider || একাধিক প্রভাইডার

বড় অ্যাপ্লিকেশনগুলিতে অনেকগুলি ভ্যালু ইনজেকশন করার সময়, Provider দ্রুত সুন্দরভাবে নেস্টেড হয়ে উঠতে পারেঃ

Provider<Something>(
  create: (_) => Something(),
  child: Provider<SomethingElse>(
    create: (_) => SomethingElse(),
    child: Provider<AnotherThing>(
      create: (_) => AnotherThing(),
      child: someWidget,
    ),
  ),
),

এর পরিবর্তেঃ

MultiProvider(
  providers: [
    Provider<Something>(create: (_) => Something()),
    Provider<SomethingElse>(create: (_) => SomethingElse()),
    Provider<AnotherThing>(create: (_) => AnotherThing()),
  ],
  child: someWidget,
)

উভয় উদাহরণের আচরণ কঠোরভাবে একই। MultiProvider শুধুমাত্র কোডের লুক পরিবর্তন করে।

ProxyProvider

3.0.0 থেকে, একটি নতুন ধরনের প্রভাইডার আছেঃ ProxyProvider

ProxyProvider হল একটি প্রভাইডার যেটি অন্যান্য প্রভাইডারদের থেকে একাধিক ভ্যালুকে একটি নতুন অবজেক্টে একত্রিত করে এবং ফলাফলটি Provider-এ পাঠায়।

সেই নতুন অবজেক্টটি আপডেট করা হবে যখনই আমরা যে প্রভাইডারের উপর নির্ভরশীল তাদের একজন আপডেট করা হবে।

নিচের উদাহরণটি অন্য প্রভাইডার থেকে আসা কাউন্টারের উপর ভিত্তি করে অনুবাদ তৈরি করতে ProxyProvider ব্যবহার করে।

Widget build(BuildContext context) {
  return MultiProvider(
    providers: [
      ChangeNotifierProvider(create: (_) => Counter()),
      ProxyProvider<Counter, Translations>(
        update: (_, counter, __) => Translations(counter.value),
      ),
    ],
    child: Foo(),
  );
}

class Translations {
  const Translations(this._value);

  final int _value;

  String get title => 'You clicked $_value times';
}

এটি একাধিক বৈচিত্রের অধীনে আসে, যেমনঃ

  • ProxyProvider বনাম ProxyProvider2 বনাম ProxyProvider3, ...

    ক্লাসের নামের পরে সেই সংখ্যা হল অন্যান্য প্রভাইডারের সংখ্যা যার উপর ProxyProvider নির্ভর করে।

  • ProxyProvider বনাম ChangeNotifierProxyProvider বনাম ListenableProxyProvider, ...

    তারা সবাই একইভাবে কাজ করে, কিন্তু একটি Provider-এ ফলাফল পাঠানোর পরিবর্তে, একটি ChangeNotifierProxyProvider এর ভ্যালু ChangeNotifierProvider-এ পাঠাবে।

সচারচর জিজ্ঞাসা

আমি কি আমার অবজেক্টের বিষয়বস্তু ইন্সপেক্ট করতে পারি?

ফ্লটার একটি ডেভটুল এর সাথে আসে যা দেখায় যে একটি নির্দিষ্ট মুহূর্তে উইজেট ট্রি কিরকম আছে।

যেহেতু প্রভাইডাররা উইজেট, তাই তারা সেই devtool-এও দৃশ্যমানঃ

সেখান থেকে, আপনি যদি একটি প্রভাইডারে ক্লিক করেন, তাহলে আপনি এটি এক্সপোস করে এমন ভ্যালু দেখতে সক্ষম হবেনঃ

(example ফোল্ডার ব্যবহার করে devtool-এর স্ক্রিনশট)

devtool শুধুমাত্র"Instance of MyClass" দেখায়। আমি কি করতে পারি?

ডিফল্টরূপে, devtool toString-এর উপর নির্ভর করে, যা ডিফল্ট হয় "Instance of MyClass"।

আরো দরকারী কিছু পেতে, আপনার দুটি সমাধান আছেঃ

  • Flutter থেকে Diagnosticable API ব্যবহার করুন।

    বেশিরভাগ ক্ষেত্রে, আমি আপনার অবজেক্টে DiagnosticableTreeMixin ব্যবহার করব, তারপরে debugFillProperties এর একটি কাস্টম ইমপ্লিমেন্টশন হবে।

    class MyClass with DiagnosticableTreeMixin {
      MyClass({this.a, this.b});
    
      final int a;
      final String b;
    
      @override
      void debugFillProperties(DiagnosticPropertiesBuilder properties) {
        super.debugFillProperties(properties);
        // এখানে আপনার ক্লাসের সমস্ত প্রপার্টিগুলো তালিকাভুক্ত করুন। 
        // আরো তথ্যের জন্য debugFillProperties এর ডকুমেন্টেশন দেখুন।
        properties.add(IntProperty('a', a));
        properties.add(StringProperty('b', b));
      }
    }
  • toString ওভাররাইড করা।

    আপনি যদি DiagnosticableTreeMixin ব্যবহার করতে না পারেন (যেমন যদি আপনার ক্লাস এমন একটি প্যাকেজে থাকে যা Flutter এর উপর নির্ভর করে না), তাহলে আপনি toString ওভাররাইড করতে পারেন।

    এটি DiagnosticableTreeMixin ব্যবহার করার চেয়ে সহজ কিন্তু কম শক্তিশালীঃ

    আপনি আপনার অব্জকটের বিশদ বিবরণ প্রসারিত/সঙ্কুচিত করতে সক্ষম হবেন না।

    class MyClass with DiagnosticableTreeMixin {
      MyClass({this.a, this.b});
    
      final int a;
      final String b;
    
      @override
      String toString() {
        return '$runtimeType(a: $a, b: $b)';
      }
    }

initState-এর মধ্যে প্রোভাইডার পাওয়ার সময় আমার একটি এক্সেপশন আসে, আমি কি করতে পারি?

এই এক্সেপশনটি ঘটছে কারণ আপনি একটি লাইফ-সাইকেল থেকে এমন একটি প্রভাইডার লিসেনের চেষ্টা করছেন যা আর কখনও কল করা হবে না।

এর অর্থ হল আপনার হয় অন্য লাইফ-সাইকেলে (build) ব্যবহার করা উচিত, অথবা স্পষ্টভাবে উল্লেখ করা উচিত যে আপনি আপডেটের বিষয়ে চিন্তা করেন না।

যেমন, পরিবর্তেঃ

initState() {
  super.initState();
  print(context.watch<Foo>().value);
}

আপনি করতে পারেনঃ

Value value;

Widget build(BuildContext context) {
  final value = context.watch<Foo>.value;
  if (value != this.value) {
    this.value = value;
    print(value);
  }
}

যা value প্রিন্ট করবে যখনই এটি পরিবর্তিত হয় (এবং শুধুমাত্র যখন এটি পরিবর্তিত হয়)।

বিকল্পভাবে, আপনি করতে পারেনঃ

initState() {
  super.initState();
  print(context.read<Foo>().value);
}

যা একবার value প্রিন্ট করবে এবং আপডেট উপেক্ষা করবে।

আমার অবজেক্টে হট-রিলোড কীভাবে পরিচালনা করবেন?

আপনি আপনার প্রদত্ত অবজেক্টকে ReassembleHandler ইমপ্লিমেন্ট করতে পারেনঃ

class Example extends ChangeNotifier implements ReassembleHandler {
  @override
  void reassemble() {
    print('Did hot-reload');
  }
}

তারপর সাধারণত provider এর সাথে ব্যবহার করা হয়ঃ

ChangeNotifierProvider(create: (_) => Example()),

আমি ChangeNotifier ব্যবহার করি এবং এটি আপডেট করার সময় আমার একটি এক্সেপশন আসে। কি ঘটেছে?

এটি সম্ভবত ঘটতে পারে কারণ আপনি ChangeNotifier এর কোনো একটি বংশধর থেকে পরিবর্তন করছেন যখন উইজেট ট্রি তৈরি হচ্ছে

একটি সাধারণ পরিস্থিতি যেখানে এটি ঘটে যখন একটি http রিকুয়েস্ট শুরু করা হয়, যেখানে ফিউচার নটিফায়ার এর ভিতরে সংরক্ষণ করা হয়ঃ

initState() {
  super.initState();
  context.read<MyNotifier>().fetchSomething();
}

এটি অনুমোদিত নয় কারণ স্টেট আপডেট সিঙ্ক্রোনাস।

এর মানে হল মিউটেশন হওয়ার আগে কিছু উইজেট তৈরি হতে পারে (পুরোনো ভ্যালু পাওয়া), অন্য উইজেটগুলি মিউটেশন সম্পূর্ণ হওয়ার পরে তৈরি হবে (একটি নতুন মান পাওয়া)। এটি আপনার UI তে অসঙ্গতি সৃষ্টি করতে পারে এবং তাই এটি অনুমোদিত নয়৷

পরিবর্তে, আপনার সেই মিউটেশনটি এমন জায়গায় করা উচিত যা পুরো ট্রিকে সমানভাবে প্রভাবিত করবেঃ

  • সরাসরি আপনার মডেলের আপনার প্রদানকারী/নির্মাতার create-এর ভিতরেঃ

    class MyNotifier with ChangeNotifier {
      MyNotifier() {
        _fetchSomething();
      }
    
      Future<void> _fetchSomething() async {}
    }

    যখন কোন "বাহ্যিক প্যারামিটার" নেই তখন এটি কার্যকর।

  • ফ্রেমের শেষে অ্যাসিঙ্ক্রোনাসঃ

    initState() {
      super.initState();
      Future.microtask(() =>
        context.read<MyNotifier>().fetchSomething(someValue);
      );
    }

    এটি সামান্য কম আদর্শ, কিন্তু মিউটেশনে প্যারমিটার পাস করার অনুমতি দেয়।

জটিল স্টেটের জন্য আমাকে কি ChangeNotifier ব্যবহার করতে হবে?

না।

আপনি আপনার স্টেট প্রতিনিধিত্ব করার জন্য যে কোনো অবজেক্ট ব্যবহার করতে পারেন. উদাহরণ স্বরূপ, একটি বিকল্প আর্কিটেকচার হল StatefulWidget এর সাথে মিলিত Provider.value() ব্যবহার করা।

এই ধরনের আর্কিটেকচার ব্যবহার করে এখানে একটি কাউন্টারের উদাহরণ রয়েছে:

class Example extends StatefulWidget {
  const Example({Key key, this.child}) : super(key: key);

  final Widget child;

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

class ExampleState extends State<Example> {
  int _count;

  void increment() {
    setState(() {
      _count++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Provider.value(
      value: _count,
      child: Provider.value(
        value: this,
        child: widget.child,
      ),
    );
  }
}

যেখানে আমরা এটি করে স্টেট রিড করতে পারিঃ

return Text(context.watch<int>().toString());

এবং স্টেটকে মডিফাই করতে পারিঃ

return FloatingActionButton(
  onPressed: () => context.read<ExampleState>().increment(),
  child: Icon(Icons.plus_one),
);

বিকল্পভাবে, আপনি আপনার নিজস্ব প্রভাইডার তৈরি করতে পারেন।

আমি কি আমার প্রভাইডার তৈরি করতে পারি?

হ্যাঁ. provider সমস্ত ছোট উপাদানগুলিকে উন্মোচিত করে যা একটি সম্পূর্ণরূপে প্রভাইডারকে তৈরি করে৷

এটা অন্তর্ভুক্তঃ

  • SingleChildStateless Widget, যেকোনো উইজেটকে MultiProvider-এর সাথে কাজ করতে এই ইন্টারফেসটি এক্সপোস হয় একটি package:provider/single_child_widget এর অংশ হিসেবে।

  • InheritedProvider, জেনেরিক InheritedWidget যা context.watch করার সময় প্রাপ্ত হয়।

এখানে 'ValueNotifier' ষ্টেট হিসাবে ব্যবহার করার জন্য একটি কাস্টম প্রভাইডারের একটি উদাহরণ রয়েছে: https://gist.github.com/rrousselGit/4910f3125e41600df3c2577e26967c91

আমার উইজেট প্রায়ই রিবিল্ট হয়। আমি কি করতে পারি?

context.watch এর পরিবর্তে, আপনি শুধুমাত্র প্রাপ্ত অবজেক্টের প্রপারটিগুলোর নির্দিষ্ট সেট শুনতে context.select ব্যবহার করতে পারেন।

উদাহরণস্বরূপ, যখন আপনি লিখতে পারেনঃ

Widget build(BuildContext context) {
  final person = context.watch<Person>();
  return Text(person.name);
}

যদি name ব্যতীত অন্য কিছু পরিবর্তন হয় তাহলে এটি উইজেটটিকে পুনর্নির্মাণ করতে পারে।

পরিবর্তে, আপনি শুধুমাত্র name প্রপারটি শুনতে context.select ব্যবহার করতে পারেনঃ

Widget build(BuildContext context) {
  final name = context.select((Person p) => p.name);
  return Text(name);
}

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

একইভাবে, আপনি Consumer/Selector ব্যবহার করতে পারেন। তাদের ঐচ্ছিক child লজিক উইজেট ট্রির শুধুমাত্র একটি নির্দিষ্ট অংশ পুনর্নির্মাণের অনুমতি দেয়:

Foo(
  child: Consumer<A>(
    builder: (_, a, child) {
      return Bar(a: a, child: child);
    },
    child: Baz(),
  ),
)

এই উদাহরণে, A আপডেট হলে শুধুমাত্র Bar পুনরায় তৈরি হবে। Foo এবং Baz অপ্রয়োজনীয়ভাবে পুনর্নির্মাণ হবে না।

আমি কি একই ধরনের টাইপ ব্যবহার করে দুটি ভিন্ন প্রভাইডার পেতে পারি?

না। আপনার কাছে একই ধরনের একাধিক প্রভাইডার শেয়ার করার সময়, একটি উইজেট তাদের মধ্যে শুধুমাত্র একটি পেতে সক্ষম হবে: যে নিকটতম।

পরিবর্তে, আপনি যদি স্পষ্টভাবে উভয় প্রভাইডারকে একটি ভিন্ন ধরনের টাইপ দেন তবে এটি সাহায্য করবে।

এর পরিবর্তেঃ

Provider<String>(
  create: (_) => 'England',
  child: Provider<String>(
    create: (_) => 'London',
    child: ...,
  ),
),

এরকম করুনঃ

Provider<Country>(
  create: (_) => Country('England'),
  child: Provider<City>(
    create: (_) => City('London'),
    child: ...,
  ),
),

আমি কি একটি ইন্টারফেস কনসিউম করতে পারি এবং একটি ইমপ্লিমেন্টশন প্রদান করতে পারি?

হ্যাঁ, কম্পাইলারকে একটি টাইপ ইঙ্গিত দিতে হবে যাতে বোঝা যায় যে ইন্টারফেসটি ব্যবহার করা হবে, তৈরিতে দেওয়া ইমপ্লিমেন্টশনের সাথে।

abstract class ProviderInterface with ChangeNotifier {
  ...
}

class ProviderImplementation with ChangeNotifier implements ProviderInterface {
  ...
}

class Foo extends StatelessWidget {
  @override
  build(context) {
    final provider = Provider.of<ProviderInterface>(context);
    return ...
  }
}

ChangeNotifierProvider<ProviderInterface>(
  create: (_) => ProviderImplementation(),
  child: Foo(),
),

বিদ্যমান প্রভাইডার

provider বিভিন্ন ধরনের অবজেক্টের জন্য কয়েকটি ভিন্ন ধরনের provider প্রকাশ করে।

উপলব্ধ সমস্ত অবজেক্টের সম্পূর্ণ তালিকা এখানে

নাম ব্যাখ্যা
Provider প্রভাইডারের সবচেয়ে মৌলিক ফর্ম. এটি একটি ভ্যালু/মান নেয় এবং এটি প্রকাশ করে, তা যাই হোক না কেন।
ListenableProvider লিসেনেবল অবজেক্টের জন্য একটি নির্দিষ্ট প্রভাইডার। ListenableProvider অবেজক্টটি লিসেন করবে এবং যখনই শ্রোতাকে ডাকা হবে তখনই এটির উপর নির্ভরশীল উইজেটগুলিকে পুনর্নির্মাণ করতে বলবে।
ChangeNotifierProvider ChangeNotifier-এর জন্য ListenableProvider-এর একটি স্পেসিফিকেশন। প্রয়োজনে এটি স্বয়ংক্রিয়ভাবে ChangeNotifier.dispose কল করবে।
ValueListenableProvider একটি ValueListenable লিসেন করুন এবং শুধুমাত্র ValueListenable.value প্রকাশ করুন।
StreamProvider একটি স্ট্রিম লিসেন করুন এবং নির্গত সর্বশেষ মান/ভ্যালু প্রকাশ করুন।
FutureProvider একটি Future নেয় এবং Future সম্পূর্ণ হলে নির্ভরশীলদের আপডেট করে।

আমার অ্যাপ্লিকেশন একটি StackOverflowError নিক্ষেপ করে কারণ আমার অনেক প্রভাইডার আছে, আমি কি করতে পারি?

আপনার যদি অনেক বেশি সংখ্যক প্রভাইডার থাকে (150+), তাহলে এটা সম্ভব যে কিছু ডিভাইস একটি StackOverflowError নিক্ষেপ করবে কারণ আপনি একবারে অনেকগুলি উইজেট তৈরি করেন।

এই পরিস্থিতিতে, আপনার কয়েকটি সমাধান আছেঃ

  • আপনার অ্যাপ্লিকেশানে যদি স্প্ল্যাশ-স্ক্রিন থাকে, তবে একবারে সব না করে সময়ের সাথে সাথে আপনার প্রভাইডারদের মাউন্ট করার চেষ্টা করুন।

    আপনি করতে পারেনঃ

    MultiProvider(
      providers: [
        if (step1) ...[
          <lots of providers>,
        ],
        if (step2) ...[
          <some more providers>
        ]
      ],
    )

    যেখানে আপনার স্প্ল্যাশ স্ক্রিন অ্যানিমেশনের সময়, আপনি করবেনঃ

    bool step1 = false;
    bool step2 = false;
    @override
    initState() {
      super.initState();
      Future(() {
        setState(() => step1 = true);
        Future(() {
          setState(() => step2 = true);
        });  
      });
    }
  • MultiProvider ব্যবহার করা থেকে অপ্ট আউট করার কথা বিবেচনা করুন। MultiProvider প্রতিটি প্রভাইডারের মধ্যে একটি উইজেট যোগ করে কাজ করে। MultiProvider ব্যবহার না করলে StackOverflowError এর লিমিট বাড়তে পারে।