flutter dependOnInheritedWidgetOfExactType() returns null

1k Views Asked by At

I am trying to use InheritedWidget approach to share state down the Widget tree. For this, I am making a simple counter app. You can add, subtract, multiply or divide the counter however you like.

It's a small demo so best practices are not followed. The line with code context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>() seem to be null for some reason. When looking at samples and doc, it should find the MyInheritedWidget in the widget tree and return it. However, I am getting complaints from flutter tool that it is null. And, in deed it is null when asserted as well.

What is the reasoning here for failed return here? And, how do I need to do it such that I can receive the instance?

File: main.dart

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Counter(),
    );
  }
}

class Counter extends StatefulWidget {
  const Counter({Key? key}) : super(key: key);

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

class CounterState extends State<Counter> {
  int counter = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Counter App'),
        centerTitle: true,
      ),
      body: MyInheritedWidget(
        counterState: this,
        child: Builder(
          builder: (BuildContext innerContext) {
            return CounterViewer(
                counterState: MyInheritedWidget.of(context).counterState);
          },
        ),
      ),
    );
  }

  void addCounter(int value) {
    setState(() {
      counter++;
    });
  }

  void subtractCounter(int value) {
    setState(() {
      counter--;
    });
  }

  void multiplyCounter(int value) {
    setState(() {
      counter *= value;
    });
  }

  void divideCounter(int value) {
    setState(() {
      counter = (counter / value).toInt();
    });
  }
}

class MyInheritedWidget extends InheritedWidget {
  final CounterState counterState;

  const MyInheritedWidget(
      {Key? key, required Widget child, required this.counterState})
      : super(key: key, child: child);

  static MyInheritedWidget of(BuildContext context) {
    final MyInheritedWidget? widget =
        context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();

    assert(widget != null);
    return widget!;
  }

  @override
  bool updateShouldNotify(covariant InheritedWidget oldWidget) {
    return true;
  }
}

class CounterViewer extends StatelessWidget {
  final CounterState counterState;

  const CounterViewer({Key? key, required this.counterState}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Container(
          color: Colors.green.shade200,
          width: MediaQuery.of(context).size.width,
          height: 180,
          child: Center(
            child: Text(
              '220',
              style: TextStyle(
                color: Colors.grey.shade50,
                fontSize: 60,
                fontWeight: FontWeight.bold,
              ),
            ),
          ),
        ),
        Container(
          color: Colors.grey.shade300,
          padding: EdgeInsets.symmetric(vertical: 16),
          child: Row(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              ElevatedButton(
                onPressed: () {},
                child: Text('Add'),
              ),
              ElevatedButton(
                onPressed: () {},
                child: Text('Subtract'),
              ),
              ElevatedButton(
                onPressed: () {},
                child: Text('Multiply'),
              ),
              ElevatedButton(
                onPressed: () {},
                child: Text('Divide'),
              ),
            ],
          ),
        )
      ],
    );
  }
}

Update: I seem to have passed the wrong context to the dependOnInheritedWidgetOfExactType() method. Changing from context to innerContext fixed the issue.

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Counter App'),
        centerTitle: true,
      ),
      body: MyInheritedWidget(
        counterState: this,
        child: Builder(
          builder: (BuildContext innerContext) {
            return CounterViewer(
                counterState: MyInheritedWidget.of(innerContext).counterState);
          },
        ),
      ),
    );
  }
0

There are 0 best solutions below