CachedNetworkImage仅显示占位符,不会在Flutter聊天应用程序中加载图像

时间:2019-01-10 15:23:09

标签: image dart flutter

首先,我是一个完整的初学者(不仅在dart / flutter中),而且在一般的编程方面。我目前正在使用聊天应用。

目标:当我在聊天屏幕中选择图像时,例如WhatsApp-它应立即显示为消息(在上载到Firestore时带有加载符号的占位符)。

问题:一切正常,但这是一个问题:当我通过图像选择器选择图像时,该图像被上传,但是在聊天中将其显示为消息之前会有一段时间。 imagepicker->写入Firestore-> Streambuilder  (listView.builder)。

我的尝试:我正在使用CachedNetworkImage,但不幸的是,它一直在显示占位符(CircularProgressIndicator),而不是实际图像。如果我只是显示图像,则一切正常(除了延迟)。

此外,我非常感谢一些想法来使应用程序运行更快/改善代码;-)。

//Chat screen which lists all the chat messages, including _handleSubmitted and the _buildTextComposer

import 'dart:math';
import 'dart:io';

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:intl/intl.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:transparent_image/transparent_image.dart';
import 'package:flutter_image/network.dart';
import 'package:flutter_native_image/flutter_native_image.dart';

final database = Firestore.instance
    .collection('nachrichten')
    .document('G5xlQHvb56ZqpWs7ojUV');
final reference = FirebaseDatabase.instance.reference().child('messages');

class ChatScreen extends StatefulWidget {
  @override
  State createState() => new ChatScreenState();
}

class ChatScreenState extends State<ChatScreen> with TickerProviderStateMixin {
  final TextEditingController _textController = new TextEditingController();
  final ScrollController _scrollController = new ScrollController();

  bool _isComposing = false;
  bool isLoading;
  String imageUrl;
  File imageFile;

  //optional from other code
  @override
  void initState() {
    super.initState();
    imageUrl = '';
  }

  Future getImage() async {
    imageFile = await ImagePicker.pickImage(source: ImageSource.camera);

    if (imageFile != null) {
      setState(() {
        isLoading = true;
      });
      uploadFile();
    }
  }

  Future uploadFile() async {
    //file compression
    File compressedFile = await FlutterNativeImage.compressImage(imageFile.path,
        quality: 100, percentage: 100);
    String fileName = DateTime.now().millisecondsSinceEpoch.toString();
    StorageReference reference = FirebaseStorage.instance.ref().child(fileName);
    StorageUploadTask uploadTask = reference.putFile(compressedFile);
    StorageTaskSnapshot storageTaskSnapshot = await uploadTask.onComplete;
    storageTaskSnapshot.ref.getDownloadURL().then((downloadUrl) {
      imageUrl = downloadUrl;
      setState(() {
        isLoading = false;
        _handleSubmitted(imageUrl: imageUrl);
      });
    }, onError: (err) {
      setState(() {
        isLoading = false;
      });
      Fluttertoast.showToast(msg: 'This file is not an image');
    });
  }

  //Builds the button text composer, including camera icon, text input and send button
  Widget _buildTextComposer() {
    return new IconTheme(
      data: new IconThemeData(color: Theme.of(context).accentColor),
      child: new Container(
          margin: const EdgeInsets.symmetric(horizontal: 0.80),
          child: new Row(children: <Widget>[
            new Container(
              margin: new EdgeInsets.symmetric(horizontal: 0.4),
              child: new IconButton(
                icon: new Icon(Icons.photo_camera),
                onPressed: getImage,
              ),
            ),
            new Flexible(
              child: Container(
                margin: const EdgeInsets.symmetric(vertical: 10.0),
                padding: EdgeInsets.all(10.0),
                decoration: new BoxDecoration(
                  border: Border.all(color: Colors.grey.shade200),
                  borderRadius: new BorderRadius.circular(20.0),
                ),

                //container with constraint limits the maximum height of the text input field
                child: new Container(
                  constraints: BoxConstraints.loose(Size.fromHeight(100.0)),
                  child: new TextField(
                    maxLines: null,
                    keyboardType: TextInputType.multiline,
                    controller: _textController,
                    onChanged: (String text) {
                      setState(() {
                        _isComposing = text.length > 0;
                      });
                    },
//                    onSubmitted: _handleSubmitted,
                    decoration: new InputDecoration.collapsed(
                        hintText: "Nachricht schreiben..."),
                  ),
                ),
              ),
            ),
            new Container(
                margin: new EdgeInsets.symmetric(horizontal: 0.4),
                child: Theme.of(context).platform == TargetPlatform.iOS
                    ? new CupertinoButton(
                        child: new Text("Send"),
                        onPressed: _isComposing
                            ? () => _handleSubmitted(text: _textController.text)
                            : null,
                      )
                    : new IconButton(
                        icon: new Icon(Icons.send),
                        onPressed: _isComposing
                            ? () => _handleSubmitted(text: _textController.text)
                            : null,
                      )),
          ]),
          decoration: Theme.of(context).platform == TargetPlatform.iOS
              ? new BoxDecoration(
                  border:
                      new Border(top: new BorderSide(color: Colors.grey[200])))
              : null),
    );
  }

  //Builds the actual chat screen with Scaffold
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
          title: new Text("Chat.here Gruppenchat"),
          centerTitle: true,
          elevation:
              Theme.of(context).platform == TargetPlatform.iOS ? 0.0 : 4.0),
      body: StreamBuilder<QuerySnapshot>(
          stream: Firestore.instance
              .collection('nachrichten')
              .orderBy('timestamp', descending: true)
              .limit(20)
              .snapshots(),
          builder:
              (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
            if (!snapshot.hasData) return Text('Loading data');
            final int documentsLength = snapshot.data.documents.length;
            return Container(
                child: Column(
                  children: <Widget>[
                    new Flexible(
                        child: new ListView.builder(
                      controller: _scrollController,
                      reverse: true,
                      itemCount: documentsLength,
                      itemBuilder: (context, int index) {
                        final DocumentSnapshot document =
                            snapshot.data.documents[index];
                        return new Container(
                          margin: const EdgeInsets.symmetric(
                              horizontal: 10.0, vertical: 10.0),
                          child: new Row(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: <Widget>[
                              new Container(
                                margin: const EdgeInsets.only(right: 16.0),
                                child: new CircleAvatar(
                                    child: new Text(
                                        document['author'].substring(0, 1))),
                              ),
                              new Expanded(
                                child: new Column(
                                  crossAxisAlignment: CrossAxisAlignment.start,
                                  children: <Widget>[
                                    new Row(
                                      children: <Widget>[
                                        new Text(document['author'],
                                            style: TextStyle(
                                                fontSize: 12.0,
                                                color: Colors.black45,
                                                fontWeight: FontWeight.bold)),
                                        new Text(
                                            ' ' +
                                                DateFormat("MMM. d. '|' HH:mm")
                                                    .format(
                                                        document['timestamp']),
                                            style: TextStyle(
                                                fontSize: 12.0,
                                                color: Colors.black45))
                                      ],
                                    ),

                                    //can be deleted. just to test the picture.
                                    (document['text'] == null)
                                        ? new Container(
                                            child: new ClipRRect(
                                              borderRadius:
                                                  new BorderRadius.circular(
                                                      7.0),
                                              child: CachedNetworkImage(
                                                placeholder: Container(
                                                  child:
                                                      CircularProgressIndicator(
                                                    valueColor:
                                                        AlwaysStoppedAnimation<
                                                                Color>(
                                                            Colors.orange),
                                                  ),
                                                  width: 200.0,
                                                  height: 200.0,
                                                  padding: EdgeInsets.all(70.0),
                                                  decoration: BoxDecoration(
                                                    color: Colors.blue,
                                                    borderRadius:
                                                        BorderRadius.all(
                                                      Radius.circular(8.0),
                                                    ),
                                                  ),
                                                ),
                                                imageUrl:
                                                    'https://wuppertal-total.de/wp-content/uploads/2019/01/stamp_schmidt_fdp.jpg',
                                                width: 200.0,
                                                height: 200.0,
                                                fit: BoxFit.cover,
                                              ),


                                            ),
                                            margin:
                                                EdgeInsets.only(right: 50.0),
                                          )

                                        : new Card(
                                            margin:
                                                EdgeInsets.only(right: 50.0),
                                            //green color for messages of yourself
                                            color:
                                                document['author'] == "Matthias"
                                                    ? Color.fromRGBO(
                                                        220, 255, 202, 1.0)
                                                    : null,
                                            child: new Container(
                                                padding: EdgeInsets.all(6.0),
                                                child: new Text(
                                                  document['text'],
                                                  style:
                                                      TextStyle(fontSize: 15.0),
                                                )),
                                            shape: RoundedRectangleBorder(
                                                borderRadius:
                                                    BorderRadius.circular(7.0)),
                                          ),

                                  ],
                                ),
                              ),
                            ],
                          ),
                        );
                      },
                    )),
                    new Divider(height: 1.0),
                    new Container(
                      decoration:
                          new BoxDecoration(color: Theme.of(context).cardColor),
                      child: _buildTextComposer(),
                    ),
                  ],
                ),
                decoration: Theme.of(context).platform == TargetPlatform.iOS
                    ? new BoxDecoration(
                        border: new Border(
                            top: new BorderSide(color: Colors.grey[200])))
                    : null);
          }),
    );
  }


  void _handleSubmitted({String text, String imageUrl}) {
    _textController.clear();
    setState(() {
      _isComposing = false;
    });

    //creation of an own document in Firestore
    Firestore.instance.runTransaction((Transaction transaction) async {
      CollectionReference reference =
          Firestore.instance.collection('nachrichten');

      await reference.add({
        "text": text,
        "author": "Matthias",
        "imageUrl": imageUrl,
        "timestamp": DateTime.now(),

        //"timestamp": FieldValue.serverTimestamp()
      });
    });

//Let the chat list jump to the newest chat message at the bottom
    _scrollController.animateTo(
      0.0,
      curve: Curves.easeOut,
      duration: const Duration(milliseconds: 300),
    );
  }

}

7 个答案:

答案 0 :(得分:4)

它对我的情况有用。我使用了cached_network_image:^ 2.0.0

flutter clean

在模拟器上退出应用程序,重新运行该应用程序。

答案 1 :(得分:1)

我刚刚更改了'imageUrl:'和'placeholder:'的顺序,现在可以使用了。奇怪的行为。感谢您的帮助。

答案 2 :(得分:1)

对我来说,解决方案是将版本降级到

cached_network_image: ^1.1.1

并运行:

flutter clean

在最新版本中,即使按照另一个答案中的描述切换了顺序,它也根本不起作用。

答案 3 :(得分:1)

尝试:

placeholder: (context, url) => Container(child: CircularProgressIndicator()),

答案 4 :(得分:1)

您需要重新安装该应用。首次安装时热重载不起作用。

答案 5 :(得分:0)

指定对我有用的图像高度。 或者您可以尝试如下操作:

   CachedNetworkImage(
   imageUrl: "your image url",
   fit: BoxFit.cover,
   width: MediaQuery.of(context).size.width,
   placeholder: (context,url) => CircularProgressIndicator(),
   errorWidget: (context,url,error) => new Icon(Icons.error),
 )

答案 6 :(得分:0)

在搜索所有网站后为我工作:=>

1.为cached_network_image安装最新的依赖:

2.如果您正在调试或运行,请停止应用

3.Flutter 干净

4.完全来自IDE

5.重新打开您的 IDE 并运行 pub get

  1. 运行 app/web/...

觉得有帮助就点个赞吧:)