为什么 Provider Package 不更改背景图像?

Why isn't the Provider Package changing the background image?

我已将提供程序包添加到我有两个屏幕的应用程序中。当用户点击应用程序上的小图片时,它会更改另一个屏幕上的主背景图片。我在两个屏幕上都调用了 Provider 和 类,但它没有在 Positioned.fill.

中返回 'myValue'

需要更改背景图片的主页屏幕:

import 'package:flutter/material.dart';
import 'package:flutter_app_background/small_images.dart';
import 'package:flutter/cupertino.dart';
import 'package:provider/provider.dart';


void main() => runApp(MyApp());


class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<MyModel>(
      create: (context) => MyModel(),
      child: MaterialApp(
        title: 'Title',
        home: HomePage(),
      ),
    );
  }
}

class HomePage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
      return Scaffold(
        extendBodyBehindAppBar: true,
        appBar: AppBar(
          title: Text('Background Image', style: TextStyle(
              color: Colors.black,
              fontSize: 16,
              fontWeight: FontWeight.bold),
          ),
          iconTheme: IconThemeData(color: Colors.white),
          actions: <Widget>[
            IconButton(
              icon: Icon(Icons.settings, color: Colors.black,),
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => SmallImages()),
                );
              },
            ),
          ],
          backgroundColor: Colors.transparent,
          elevation: 0.0,
        ),
        body: Stack(
          children: <Widget>
          [
            Positioned.fill(
              child: GestureDetector(
                child: Consumer<MyModel>(
                  builder: (context, myModel, child) {
                    return myModel.bgImage;
                    // return myValue;
                  },
                ),
              ),
            ),
          ],
        ),
      );
    }
}

class MyModel extends ChangeNotifier {
  Image bgImage = Image.asset('images/background_image.jpeg', fit: BoxFit.fill);

}

用户点击小图像更改主页背景的小图像屏幕。

import 'package:flutter/material.dart';
import 'package:flutter_app_background/main.dart';
import 'package:provider/provider.dart';


class SmallImages extends StatefulWidget {
  static int tappedGestureDetector = 1;

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

class _SmallImagesState extends State<SmallImages> {

  List<bool> isSelected;

  void initState() {
    isSelected = [true, false, false, false, false, false, false, false, false];
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final myModel = Provider.of<MyModel>(context,listen:true); //default for listen is `true`
    return Scaffold(
          appBar: AppBar(
            title: Text('Small Image', style: TextStyle(
                color: Colors.black, fontSize: 16, fontWeight: FontWeight.bold),
            ),
            iconTheme: IconThemeData(color: Colors.white),
            actions: <Widget>[
              IconButton(
                icon: Icon(Icons.arrow_left, color: Colors.black,),
                onPressed: () {
                  Navigator.pop(
                    context,
                    MaterialPageRoute(builder: (context) => HomePage()),
                  );
                },
              ),
            ],
            backgroundColor: Colors.transparent,
            elevation: 0.0,
          ),
          body: Material(
            child: GestureDetector(
              child: MaterialApp(
                  builder: (context, snapshot) {
                    return GridView.count(
                      crossAxisCount: 1,
                      childAspectRatio: 1.0,
                      padding: const EdgeInsets.all(4.0),
                      mainAxisSpacing: 0.0,
                      crossAxisSpacing: 0.0,
                      children: [
                        GridView(
                          gridDelegate:
                          SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3,
                            childAspectRatio: MediaQuery
                                .of(context)
                                .size
                                .width /
                                (MediaQuery
                                    .of(context)
                                    .size
                                    .height / 2),
                          ),
                          children: [
                              GestureDetector(
                                onTap: () {
                                  setState(() {
                                    SmallImages.tappedGestureDetector = 1;
                                  });
                                  myModel.bgImage = Image.asset('images/iceland_background.jpg');
                                },
                                child: Container(
                                  height: 100,
                                  width: 107,
                                  decoration: BoxDecoration(border: SmallImages
                                      .tappedGestureDetector == 1
                                      ? Border.all(
                                      color: Color(0xff2244C7), width: 1.0)
                                      : Border
                                      .all(color: Colors.transparent,),),
                                  child: Image.asset(
                                    'images/nightsky_image.png',
                                  ),
                                ),
                            ),
                            Consumer<MyModel>(
                              builder: (context, myModel, child) {
                                return GestureDetector(
                                  onTap: () {
                                    setState(() {
                                      SmallImages.tappedGestureDetector = 2;
                                    }); // <-- replaced 'tapped' and 'other'
                                  },
                                  child: Container(
                                    height: 100,
                                    width: 107,
                                    decoration: BoxDecoration(border: SmallImages
                                        .tappedGestureDetector == 2
                                        ? Border.all(
                                        color: Color(0xff2244C7), width: 1.0)
                                        : Border
                                        .all(color: Colors.transparent,),),
                                    child: Image.asset(
                                      'images/own_image.png',
                                    ),
                                  ),
                                );
                              },
                            ),
                            Consumer<MyModel>(
                              builder: (context, myModel, child) {
                                return GestureDetector(
                                  onTap: () {
                                    setState(() {
                                      SmallImages.tappedGestureDetector = 3;
                                    }); // <-- replaced 'tapped' and 'other'
                                  },
                                  child: Container(
                                    height: 100,
                                    width: 107,
                                    decoration: BoxDecoration(border: SmallImages
                                        .tappedGestureDetector == 3
                                        ? Border.all(
                                        color: Color(0xff2244C7), width: 1.0)
                                        : Border
                                        .all(color: Colors.transparent,),),
                                    child: Image.asset(
                                      'images/iceland_image.png',
                                    ),
                                  ),
                                );
                              },
                            ),
                          ].toList(),
                        ),
                      ],
                    );
                  }),
            ),
          ),
        );
  }
}

您应该使用提供商包装 material 应用程序:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Provider<MyModel>(
      create: (context) => MyModel(),
      child: MaterialApp(
        title: 'Title',
        home: HomePage(),
      );
    )

  }
}

如果你想让它在 MyModel 发生变化时重建一些小部件,你应该像这样使用 ChangeNotifer 扩展 MyModel:

class MyModel extends ChangeNotifier{
final bgImage = //someimage

而不是 MaterialApp 周围的 Provider,您应该像这样使用 ChangeNotifierProvider

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<MyModel>(
      create: (context) => MyModel(),
      child: MaterialApp(
        title: 'Title',
        home: HomePage(),
      );
    )

  }
}

之后,您应该像这样在小部件中包含提供程序:

  @override
  Widget build(BuildContext context) {
    final mymodel = Provider.of<MyModel>(context); // injecting the provider
    return Container ( .....

你可以像这样在容器内使用背景图片,

color:mymodel.bgImage

一旦您更改,mymodel.bgImage 小部件将自动重建。

如果您打算在 widget tree 中重建特定的 widget,您可以在这种情况下删除此类注入 final mymodel = Provider.of<MyModel>(context); 并仅包装该特定的 widget Consumer<MyModel> 像这样:

Container(
  child:Consumer<MyModel>(
    builder: (context, myModel, child) {
    return Text("${myModel.text}"); // supposing that `text` is inside the `MyModel`
  },
)

如果您不需要在 Container 下使用 child 和 context,您可以这样做:

child:Consumer<MyModel>(
    builder: (_, myModel, _) {

更改 myModel.bgImage 的示例如下所示:

FlatButton(
onPressed: (val){
  myModel.image = otherImage  // changeing the value of my model while pressing on the button

  }
)

在按下按钮时更改我的模型的值将重建任何注入 MyModel Provider 的小部件,并且 Provider listen 属性 设置为 true,(听属性 默认设置为 true)

listen的例子属性:

final mymodel = Provider.of<MyModel>(context,listen:false) //default for listen is `true`