【问题标题】:Flutter: How to pass a value in to another class from a streamprovider / listview builderFlutter:如何将值从 streamprovider / listview builder 传递给另一个类
【发布时间】:2020-12-30 04:00:10
【问题描述】:

背景:

我正在尝试生成可滚动的图像列表视图。该屏幕将分为三个阶段:

  • 最初列出某种类型的图像(在元数据中的 firestore 字段中定义)
  • 当用户选择其中一个小部件时,图像将更改为不同类型的图像
  • 最后,可选的第三阶段显示不同的类型

每次按下时,所选图像将构建到一个新数组中,最终形成另一种由三个所选图像组成的图像视图,将在底部显示,单击按钮将读取“ 3 个选定图像的句子”。

我目前拥有的:

我通过调用包含 ListView 的类的 StreamProvider 提供了带有正确过滤图像的初始 ListView。目前这已被过滤,因为我对查询进行了硬编码。

这是最终显示 ListView 的屏幕

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:showmeapp/Screens/Home/image_list.dart';
import 'package:showmeapp/Services/database.dart';
import 'package:showmeapp/models/new_image.dart';

class Sentence extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

    return StreamProvider<List<NewImage>>.value(
      value: FirestoreDatabaseService().firestoreImages,
      child: Scaffold(
        backgroundColor: Colors.blue[300],
        appBar: AppBar(
          title: Text('Make A Sentence'),
          backgroundColor: Colors.blue[700],
          elevation: 0.0,
        ),
        body: ImageList(),
      )
    );
  }
}

这是从该屏幕调用的 ImageList 类

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:showmeapp/Screens/Home/image_card.dart';
import 'package:showmeapp/models/new_image.dart';

class ImageList extends StatefulWidget {
  @override
  _ImageListState createState() => _ImageListState();

}

class _ImageListState extends State<ImageList> {
  @override
  Widget build(BuildContext context) {
    
    final images = Provider.of<List<NewImage>>(context) ?? [];
    final requestImages = images.where((element) => element.imageClass == 'request').toList();
    
    return ListView.builder(
      scrollDirection: Axis.horizontal,
      itemCount: requestImages.length,
      itemBuilder: (context, index) {
        return Container(
          padding: EdgeInsets.symmetric(horizontal: 12.0, vertical: 24.0),
          height: MediaQuery.of(context).size.height * 0.35,
          child: ImageCard(newImage: requestImages[index]),
        );
      },
    );
  }
}

这是从 ImageList 类调用的自定义 ImageCard 类

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:showmeapp/Screens/Home/image_list.dart';
import 'package:showmeapp/models/new_image.dart';

class ImageCard extends StatelessWidget {
  final NewImage newImage;

  ImageCard({this.newImage});

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Container(
          width: MediaQuery.of(context).size.width * 0.3,
          height: MediaQuery.of(context).size.height * 0.2,
          child: Card(
            elevation: 30.0,
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(5.0),
              side: BorderSide(width: 2.0, color: Colors.blueAccent),
            ),
            child: GestureDetector(
              child: Padding(
                padding: const EdgeInsets.all(8.0),
                child: Image.asset(
                  'assets/${newImage.imageLocation}',
                  scale: 0.8,
                  height: MediaQuery.of(context).size.height * 0.2,
                  width: MediaQuery.of(context).size.width * 0.1,
                ),
              ),
              onTap: () {
                // String optionSelected = newImage.imageClass;

              },
            ),
          ),
        ),
        Container(
          width: MediaQuery.of(context).size.width * 0.3,
          child: Padding(
            padding: EdgeInsets.all(5.0),
            child: Center(
              child: Text(
                newImage.imageDescription,
                style: TextStyle(
                  fontSize: 40.0,

                ),
              ),
            ),
          ),
        )
      ],
    );
  }
}

最后,为了完整起见,这是与 Firebase 相关的函数和所有这些背后的调用

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:showmeapp/models/new_image.dart';

// A class for the Firestore Database Service

class FirestoreDatabaseService {

  final String iid;
  
  // Constructor for Database Class
  FirestoreDatabaseService({ this.iid });
  
  // create a reference to the Firestore 'images' collection
  final CollectionReference firestoreImageCollection = FirebaseFirestore.instance.collection('images');
  
  // Add or update image data - This will be useful for initial creation of image meta data for the app
  Future updateFirestoreImageData(String description, String location, String type, String category) async {
    return await firestoreImageCollection.doc(iid).set({
      'image_category': category,
      'image_description': description,
      'image_location': location,
      'image_type': type
    });
  }
  
  // new image list from snapshot
  List<NewImage> _newImageFromSnapshot(QuerySnapshot snapshot) {
    return snapshot.docs.map((doc) {
      return NewImage(
        imageClass: doc.data()['image_class'] ?? '',
        imageType: doc.data()['image_type'] ?? '',
        imageCategory: doc.data()['image_category'] ?? '',
        imageLocation: doc.data()['image_location'] ?? '',
        imageDescription: doc.data()['image_description'] ?? ''
      );
    }).toList();
  }

  // Get images from collection via stream
  Stream<List<NewImage>> get firestoreImages {
    return firestoreImageCollection.snapshots()
      .map(_newImageFromSnapshot);
  }
}

我正在努力解决的问题:

当用户选择“请求”图像之一时,我想传递一个值,以便下一组显示的图像属于“对象”类型。

但是如果我通过它,它总是将请求的提供者作为 Null 发送并且什么都不返回。

不起作用的代码:

ImageList 类

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:showmeapp/Screens/Home/image_card.dart';
import 'package:showmeapp/models/new_image.dart';

class ImageList extends StatefulWidget {
  @override
  _ImageListState createState() => _ImageListState();

  String searchClass;
  ImageList({ this.searchClass });
}

class _ImageListState extends State<ImageList> {
  @override
  Widget build(BuildContext context) {
    final String searchClass = ImageList().searchClass;
    final images = Provider.of<List<NewImage>>(context) ?? [];
    final requestImages = images.where((element) => element.imageClass == searchClass.toString()).toList();
    print('search class is: $searchClass');
    print('Class search class is: ${ImageList().searchClass}');
    
    return ListView.builder(
      scrollDirection: Axis.horizontal,
      itemCount: requestImages.length,
      itemBuilder: (context, index) {
        return Container(
          padding: EdgeInsets.symmetric(horizontal: 12.0, vertical: 24.0),
          height: MediaQuery.of(context).size.height * 0.35,
          child: ImageCard(newImage: requestImages[index]),
        );
      },
    );
  }
}

句子屏幕/小部件

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:showmeapp/Screens/Home/image_list.dart';
import 'package:showmeapp/Services/database.dart';
import 'package:showmeapp/models/new_image.dart';

class Sentence extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

    return StreamProvider<List<NewImage>>.value(
      value: FirestoreDatabaseService().firestoreImages,
      child: Scaffold(
        backgroundColor: Colors.blue[300],
        appBar: AppBar(
          title: Text('Make A Sentence'),
          backgroundColor: Colors.blue[700],
          elevation: 0.0,
        ),
        body: ImageList(searchClass: 'request',),
      )
    );
  }
}

因此,传递“请求”字符串并将其包含在 where 子句中会导致 Null。它仅在我在 where 子句中硬指定“请求”时才有效。上面的示例不是来自所选图像的操作,但与我试图告诉它最初通过传递的值加载“请求”图像的原理相同。一旦我可以通过初始值,那么我希望任何进一步的传递将插入到位:-)

我尝试了类、类和状态中的变量的变体(就像现在一样),但似乎无法让它携带值。

我将如何实现这一目标?是否可以使用 StreamProvider / ListView 构建器?

更新 我的 NewImage 类如下:

class NewImage {

  final String imageType; // Whether the image is a Category image or Object Image
  final String imageDescription; // Text to display with the image
  final String imageLocation; // The URL or Location of the image
  final String imageCategory; // The category that the image belongs to
  final String imageClass; // A tag to identify the stage for sentences, such as Request, Object, Ending

  NewImage({ this.imageType, this.imageDescription, this.imageLocation, this.imageCategory, this.imageClass });

}

谢谢

安德鲁

【问题讨论】:

    标签: android-studio flutter listview dart google-cloud-firestore


    【解决方案1】:

    我不完全确定我是否理解你的问题,但是我认为你的问题是由这行引起的:

    final images = Provider.of<List<NewImage>>(context) ?? [];
    

    我假设你的 new_image.dart 模型是这样的:

    class NewImage extends ChangeNotifier {
      List<Image> _imageList = [];
      List<Image> get imageList => _imageList;
      void fetchImages() {
        _imageList = fetchFunction();
        notifyListeners();
      }
     ....
    }
    

    如果是这种情况,您的代码应该是这样的:

    final images = Provider.of<NewImage>(context, listen: false).imageList;
    

    【讨论】:

    • 嗨,我已经更新了我的帖子以显示 NewImage 类。但是不,它只是我的图像对象的标准模型
    猜你喜欢
    • 2022-09-27
    • 1970-01-01
    • 1970-01-01
    • 2018-02-05
    • 1970-01-01
    • 2014-02-24
    • 2020-09-13
    • 2012-01-11
    相关资源
    最近更新 更多