颤抖处理数据更好

时间:2018-03-02 17:43:10

标签: dart flutter

我有一个FutureBuilder从本地sqlite DB获取DISTINCT日期,然后我获取每个日期并获取这些日期的消息以将它们放入小部件中,这样可以正常工作,直到您想实时收听流或轮询重建窗口小部件并闪烁页面的新消息,然后每次滚动到开头。我希望找到一种方法将所有数据带入一些对象或其他小部件,然后按日期和顺序分组等。这样我就可以收听流更新消息等。

任何帮助都会很棒,这是我的代码,如果它可以帮助任何人看到我做的事情,这是在我转换为Streambuilder后,但结果相同。

new StreamBuilder(
              initialData: myInitialData,
              stream: msgstream,
              builder: (BuildContext context, AsyncSnapshot<List<Map>> snapshot) {
                switch (snapshot.connectionState) {
                  case ConnectionState.none:
                    return new Text('Waiting to start');
                  case ConnectionState.waiting:
                    return new Text('');
                  default:
                    if (snapshot.hasError) {
                      return new Text('Error: ${snapshot.error}');
                    } else {
                      myInitialData = snapshot.data;
                      return new RefreshIndicator(
                          child: new ListView.builder(
                            itemBuilder: (context, index) {
                              return new MyChatWidget(
                                datediv: snapshot.data[index]['msgdate'],
                                msgkey: snapshot.data[index]['msgkey'],
                              );

                            },
                            //itemBuilder: _itemBuilder,
                            controller: _scrollController,
                            reverse: true,
                            itemCount: snapshot.data.length,
                          ),
                          onRefresh: _onRefresh
                      );
                    }

                }
              }),

这是StreamBuilder调用的Widget:

class MyChatWidget extends StatefulWidget {
  MyChatWidget({Key key, this.datediv, this.msgkey}) : super(key: key);

  final String datediv;
  final String msgkey;

  @override
  _MyChatWidgetState createState() => new _MyChatWidgetState();
}

class _MyChatWidgetState extends State<MyChatWidget> {
  List<Widget> messagelist;
  int messagecount = 0;
  var jsonCodec = const JsonCodec();
  var mydate = '';
  var _urlMessages = '';
  PageStorageKey _key;
  VideoPlayerController vcontroller;

  //Future<http.Response> _responseFuture;
  Future<List<Map>> _responseFuture;
  List messList;
  var mybytes;
  File myimageview;
  Image newimageview;
  String imgStr;
  String vidStr;
  String vidimgstr;
  bool submitting = false;
  List<Map> myInitialData;
  Stream<List<Map>> msgstream;

  @override
  void initState() {
    super.initState();
    if (new DateFormat.yMd().format(DateTime.parse(widget.datediv)) ==
        new DateFormat.yMd().format(new DateTime.now())) {
      mydate = 'Today';
    } else {
      mydate = new DateFormat.yMMMEd().format(DateTime.parse(widget.datediv));
    }
    DateChatMessage dcm =
        new DateChatMessage(widget.msgkey, widget.datediv.toString());
    var json = jsonCodec.encode(dcm);
    _urlMessages =
        'http://loop-dev.clinicalsoftworks.com/chat/messages/getbydate';
    //_responseFuture = http.post(_urlMessages, body: json, headers: getAuthHeader());
    _responseFuture =
        ChatDB.instance.getMessagesByDate(widget.msgkey, widget.datediv);
    msgstream = new Stream.fromFuture(_responseFuture);

    //controller = new TabController(length: 4, vsync: this);
    //_getMessages();
  }

  /*@override
  void dispose() {
    super.dispose();
    if (vcontroller != null) {
      vcontroller.dispose();
    }

  }*/

  @override
  Widget build(BuildContext context) {
    _key = new PageStorageKey('${widget.datediv.toString()}');

    return new Column(
      children: <Widget>[
        new Container(
          child: new Text(
            mydate,
            textAlign: TextAlign.left,
            style: new TextStyle(
              color: Colors.grey,
              fontWeight: FontWeight.bold,
            ),
          ),
          alignment: Alignment.centerLeft,
          padding: new EdgeInsets.only(left: 10.0),
        ),
        new Container(
          child: new Divider(
            height: 5.0,
            color: Colors.grey,
          ),
          padding: new EdgeInsets.only(left: 10.0, right: 10.0),
        ),
        /**/

        new StreamBuilder(
          initialData: myInitialData,
          stream: msgstream,
          builder: (BuildContext context, AsyncSnapshot<List<Map>> snapshot) {
            switch (snapshot.connectionState) {
              case ConnectionState.none:
                return new Text('Waiting to start');
              case ConnectionState.waiting:
                return new Text('');
              default:
                myInitialData = snapshot.data;
                List<dynamic> json = snapshot.data;
                messagelist = [];
                json.forEach((element) {

                  DateTime submitdate =
                  DateTime.parse(element['submitdate']).toLocal();
                  String myvideo = (element['chatvideo']);
                  String myimage = element['chatimage'];
                  String myvideoimage = element['chatvideoimage'];
                  File imgfile;
                  File vidfile;
                  File vidimgfile;
                  bool vidInit = false;
                  Future<Null> _launched;
                  String localAssetPath;
                  String localVideoPath;
                  String mymessage = element['message'].replaceAll("[\u2018\u2019]", "'");
                  //print('MYDATE: '+submitdate.toString());
                  _checkFile(File file) async {
                    var checkfile = await file.exists();
                    print('VIDEXISTS: '+checkfile.toString());
                  }
                  Future<Null> _launchVideo(String url, bool isLocal) async {
                    if (await canLaunchVideo(url, isLocal)) {
                      await launchVideo(url, isLocal);
                    } else {
                      throw 'Could not launch $url';
                    }
                  }
                  void _launchLocal() =>
                      setState(() => _launched = _launchVideo(localVideoPath, true)
                      );

                  Widget _showVideo() {
                    /*return new Flexible(
                      child: new vplayer.VideoCard(
                        controller: vcontroller,
                        title: element['referralname'],
                        subtitle: 'video',
                      ),
                    );*/
                    return new Flexible(
                        child: new Card(
                          child: new Column(
                            children: <Widget>[
                              new ListTile(subtitle: new Text('Video'), title: new Text(element['referralname']),),
                              new GestureDetector(
                                onTap: _launchLocal,
                                child: new Image.file(
                                  vidimgfile,
                                  width: 150.0,
                                ),
                              ),
                            ],
                          ),
                        )
                    );
                  }

                  _initVideo() {
                    setState(() {vidInit = true;});
                  }

                  _onError() {
                    print('VIDEO INIT ERROR');
                  }

                  if (myimage != "") {
                    imgStr = element['chatimage'];
                    imgfile = new File(imgStr);
                  }
                  if (myvideo != "") {
                    vidStr = element['chatvideo'];
                    vidimgstr = element['chatvideoimage'];
                    vidimgfile = new File(vidimgstr);
                    //vidfile = new File(vidStr);
                    //_checkFile(vidfile);
                    //print('vidfile: '+vidfile.path);
                    localVideoPath = '$vidStr';
                    //print('LOCALVIDEO: '+localVideoPath);
                    //vcontroller = new VideoPlayerController('file://$vidStr')..initialize();

                  }

                  _showLgPic() {
                    Route route = new MaterialPageRoute(
                      settings: new RouteSettings(name: "/ShowPic"),
                      builder: (BuildContext context) => new ShowPic(
                        image: imgfile,
                      ),
                    );
                    Navigator.of(context).push(route);
                  }

                  Widget _showGraphic() {
                    Widget mywidget;
                    if (myimage != "") {
                      mywidget = new GestureDetector(
                        child: new Image.file(
                          imgfile,
                          width: 300.0,
                        ),
                        onTap: _showLgPic,
                      );
                    } else if (myvideo != "") {
                      mywidget = _showVideo();
                    } else {
                      mywidget = new Container();
                    }
                    return mywidget;
                  }

                  messagelist.add(
                    new Container(
                      //width: 300.0,
                      padding: new EdgeInsets.all(10.0),
                      child: new Column(
                        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                        crossAxisAlignment: CrossAxisAlignment.stretch,
                        mainAxisSize: MainAxisSize.min,
                        children: <Widget>[
                          new Container(
                            padding: new EdgeInsets.only(bottom: 5.0),
                            child: new Row(
                              mainAxisSize: MainAxisSize.min,
                              children: <Widget>[
                                new CircleAvatar(
                                  child: new Text(
                                    element['sendname'][0],
                                    style: new TextStyle(fontSize: 15.0),
                                  ),
                                  radius: 12.0,
                                ),
                                new Text('    '),
                                new Text(
                                  element['sendname'],
                                  style: new TextStyle(
                                      fontSize: 15.0,
                                      fontWeight: FontWeight.bold),
                                ),
                                new Text('    '),
                                new Text(
                                  new DateFormat.Hm().format(submitdate),
                                  style: new TextStyle(
                                      color: Colors.grey, fontSize: 12.0),
                                ),

                              ],
                            ),
                          ),
                          new Row(
                            children: <Widget>[
                              new Text('          '),
                              new Flexible(
                                child: new Text(mymessage),
                              )
                            ],
                          ),
                          new Container(
                              width: 150.0,
                              child: new Row(
                                children: <Widget>[
                                  new Text('          '),
                                  _showGraphic()
                                  /*myimage != ""
                                      ? new GestureDetector(
                                          child: new Image.file(
                                            imgfile,
                                            width: 300.0,
                                          ),
                                          onTap: _showLgPic,
                                        )
                                      : myvideo != "" ? _showVideo() : new Container(),*/
                                ],
                              )),
                        ],
                      ),
                    ),
                  );
                });
                return new Column(children: messagelist);
            }
          },
        )
      ],
    );
  }
}

感谢您的帮助

1 个答案:

答案 0 :(得分:0)

  

重建窗口小部件并闪烁页面,然后每次滚动到开头

要解决滚动问题,请尝试ScrollController。创建自己的,保持更新并注入您创建的列表。

要解决闪烁问题,可以使用Key列表小部件。密钥应该是消息的唯一标识符,例如msgkey

这个例子如何保持scrolloffset对我有用

class SomeWidget extends StatefulWidget {
  @override
  _SomeWidgetState createState() => new _SomeWidgetState();
}

class _SomeWidgetState extends State<SomeWidget> {
  ScrollController _scrollController;
  int _count;

  @override
  void initState() {
    super.initState();
    _count = 10;
    _scrollController = new ScrollController();
  }

  void _add() {
    setState(() => _count += 5);
  }

  @override
  Widget build(BuildContext context) {
    final _titles = new List<String>.generate(_count, (i) => 'Title ${i}');
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Demo"),
        actions: <Widget>[
          new IconButton(icon: new Icon(Icons.add), onPressed: _add)
        ],
      ),
      body: new ListView.builder(
        controller: _scrollController,
        itemCount: _titles.length,
        itemBuilder: (context, index) => new ListTile(
              title: new Text(_titles[index]),
            ),
      ),
    );
  }
}