Android 颤振:如何防止重建整个可重排序Listview?

Android 颤振:如何防止重建整个可重排序Listview?,android,flutter,dart,flutter-dependencies,dart-pub,Android,Flutter,Dart,Flutter Dependencies,Dart Pub,目前,我正在使用颤振软件包“Reorderables”来显示一个包含多个图像的可重排序列表视图。这些图像可以通过一个按钮从列表视图中删除,一切正常。但每次删除图像时,listview都会重新生成。我正在使用一个名为“ReorderableListviewManager”的类和ChangeNotifier来更新图像,并使用Provider.of(context)来获取最新图像。现在的问题是使用Provider.of(context)使得每次删除图像时都调用build()。我知道我 可以使用cons

目前,我正在使用颤振软件包“Reorderables”来显示一个包含多个图像的可重排序列表视图。这些图像可以通过一个按钮从列表视图中删除,一切正常。但每次删除图像时,listview都会重新生成。我正在使用一个名为“ReorderableListviewManager”的类和ChangeNotifier来更新图像,并使用
Provider.of(context)
来获取最新图像。现在的问题是使用
Provider.of(context)
使得每次删除图像时都调用
build()。我知道我
可以使用consumer只重建小部件树的一部分,但似乎没有地方将consumer放入此Listview的
子项中。有没有办法只重建图像而不重建整个ReorderableListview?非常感谢

下面是我的代码:

class NotePicturesEditScreen extends StatefulWidget {
  final List<Page> notePictures;
  final NotePicturesEditBloc bloc;
  NotePicturesEditScreen({@required this.notePictures, @required this.bloc});

  static Widget create(BuildContext context, List<Page> notePictures) {
    return Provider<NotePicturesEditBloc>(
      create: (context) => NotePicturesEditBloc(),
      child: Consumer<NotePicturesEditBloc>(
          builder: (context, bloc, _) =>
              ChangeNotifierProvider<ReorderableListviewManager>(
                create: (context) => ReorderableListviewManager(),
                child: NotePicturesEditScreen(
                  bloc: bloc,
                  notePictures: notePictures,
                ),
              )),
      dispose: (context, bloc) => bloc.dispose(),
    );
  }

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

class _NotePicturesEditScreenState extends State<NotePicturesEditScreen> {
  PreloadPageController _pageController;
  ScrollController _reorderableScrollController;
  List<Page> notePicturesCopy;
  int longPressIndex;
  List<double> smallImagesWidth;
  double scrollOffset = 0;

  _reorderableScrollListener() {
    scrollOffset = _reorderableScrollController.offset;
  }

  @override
  void initState() {
    Provider.of<ReorderableListviewManager>(context, listen: false)
        .notePictures = widget.notePictures;
    notePicturesCopy = widget.notePictures;
    _reorderableScrollController = ScrollController();
    _pageController = PreloadPageController();
    _reorderableScrollController.addListener(_reorderableScrollListener);
    Provider.of<ReorderableListviewManager>(context, listen: false)
        .getSmallImagesWidth(notePicturesCopy, context)
        .then((imagesWidth) {
      smallImagesWidth = imagesWidth;
    });
    super.initState();
  }

  @override
  void dispose() {
    _pageController.dispose();
    _reorderableScrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    ReorderableListviewManager reorderableManager =
        Provider.of<ReorderableListviewManager>(context, listen: false);
    return SafeArea(
      child: Scaffold(
          appBar: AppBar(
            backgroundColor: Colors.white,
            shape: Border(bottom: BorderSide(color: Colors.black12)),
            iconTheme: IconThemeData(color: Colors.black87),
            elevation: 0,
            automaticallyImplyLeading: false,
            titleSpacing: 0,
            centerTitle: true,
            title: Row(
              mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                Container(
                  child: IconButton(
                    padding: EdgeInsets.only(left: 20, right: 12),
                    onPressed: () => Navigator.of(context).pop(),
                    icon: Icon(Icons.close),
                  ),
                ),
                Text('編輯',
                    style: TextStyle(color: Colors.black87, fontSize: 18))
              ],
            ),
            actions: <Widget>[
              FlatButton(
                onPressed: () {},
                child: Text(
                  '下一步',
                ),
              )
            ],
          ),
          backgroundColor: Color(0xffeeeeee),
          body: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Spacer(),
              StreamBuilder<List<Page>>(
                initialData: widget.notePictures,
                stream: widget.bloc.notePicturesStream,
                builder: (context, snapshot) {
                  notePicturesCopy = snapshot.data;
                  return Container(
                    margin: EdgeInsets.symmetric(horizontal: 20),
                    height: MediaQuery.of(context).size.height * 0.65,
                    child: PreloadPageView.builder(
                        preloadPagesCount: snapshot.data.length,
                        controller: _pageController,
                        itemCount: snapshot.data.length,
                        onPageChanged: (index) {
                          reorderableManager.updateCurrentIndex(index);
                          reorderableManager.scrollToCenter(
                              smallImagesWidth,
                              index,
                              scrollOffset,
                              _reorderableScrollController,
                              context);
                        },
                        itemBuilder: (context, index) {
                          return Container(
                            child: Image.memory(
                              File.fromUri(
                                      snapshot.data[index].polygon.isNotEmpty
                                          ? snapshot.data[index]
                                              .documentPreviewImageFileUri
                                          : snapshot.data[index]
                                              .originalPreviewImageFileUri)
                                  .readAsBytesSync(),
                              gaplessPlayback: true,
                              alignment: Alignment.center,
                            ),
                          );
                        }),
                  );
                },
              ),
              Spacer(),
              Container(
                  height: MediaQuery.of(context).size.height * 0.1,
                  margin: EdgeInsets.symmetric(horizontal: 20),
                  child: SingleChildScrollView(
                    scrollDirection: Axis.horizontal,
                    child: ReorderableRow(
                        scrollController: _reorderableScrollController,
                        buildDraggableFeedback: (context, constraints, __) =>
                            Container(
                              width: constraints.maxWidth,
                              height: constraints.maxHeight,
                              child: Image.memory(File.fromUri(
                                      notePicturesCopy[longPressIndex]
                                              .polygon
                                              .isNotEmpty
                                          ? notePicturesCopy[longPressIndex]
                                              .documentPreviewImageFileUri
                                          : notePicturesCopy[longPressIndex]
                                              .originalPreviewImageFileUri)
                                  .readAsBytesSync()),
                            ),
                        onReorder: (oldIndex, newIndex) async {
                          List<Page> result = await widget.bloc.reorderPictures(
                              oldIndex,
                              newIndex,
                              reorderableManager.notePictures);
                          _pageController.jumpToPage(newIndex);
                          reorderableManager.updateNotePictures(result);
                          reorderableManager
                              .getSmallImagesWidth(result, context)
                              .then((imagesWidth) {
                            smallImagesWidth = imagesWidth;
                          });
                        },
                        footer: Container(
                          width: 32,
                          height: 32,
                          margin: EdgeInsets.only(left: 16),
                          child: SizedBox(
                            child: FloatingActionButton(
                              backgroundColor: Colors.white,
                              elevation: 1,
                              disabledElevation: 0,
                              highlightElevation: 1,
                              child: Icon(Icons.add, color: Colors.blueAccent),
                              onPressed: notePicturesCopy.length >= 20
                                  ? () {
                                      Scaffold.of(context)
                                          .showSnackBar(SnackBar(
                                        content: Text('筆記上限為20頁 !'),
                                      ));
                                    }
                                  : () async {
                                      List<Page> notePictures =
                                          await widget.bloc.addPicture(
                                              reorderableManager.notePictures);
                                      List<double> imagesWidth =
                                          await reorderableManager
                                              .getSmallImagesWidth(
                                                  notePictures, context);
                                      smallImagesWidth = imagesWidth;
                                      reorderableManager.updateCurrentIndex(
                                          notePictures.length - 1);
                                      reorderableManager
                                          .updateNotePictures(notePictures);
                                      _pageController
                                          .jumpToPage(notePictures.length - 1);
                                    },
                            ),
                          ),
                        ),
                        children: Provider.of<ReorderableListviewManager>(
                                context) 
                            .notePictures
                            .asMap()
                            .map((index, page) {
                              return MapEntry(
                                  index,
                                  Consumer<ReorderableListviewManager>(
                                    key: ValueKey('value$index'),
                                    builder: (context, manager, _) =>
                                        GestureDetector(
                                      onTapDown: (_) {
                                        longPressIndex = index;
                                      },
                                      onTap: () {
                                        reorderableManager.scrollToCenter(
                                            smallImagesWidth,
                                            index,
                                            scrollOffset,
                                            _reorderableScrollController,
                                            context);
                                        _pageController.jumpToPage(index);
                                      },
                                      child: Container(
                                          margin: EdgeInsets.only(
                                              left: index == 0 ? 0 : 12),
                                          decoration: BoxDecoration(
                                              border: Border.all(
                                                  width: 1.5,
                                                  color: index ==
                                                          manager
                                                              .getCurrentIndex
                                                      ? Colors.blueAccent
                                                      : Colors.transparent)),
                                          child: index + 1 <=
                                                  manager.notePictures.length
                                              ? Image.memory(
                                                  File.fromUri(manager
                                                              .notePictures[
                                                                  index]
                                                              .polygon
                                                              .isNotEmpty
                                                          ? manager
                                                              .notePictures[
                                                                  index]
                                                              .documentPreviewImageFileUri
                                                          : manager
                                                              .notePictures[
                                                                  index]
                                                              .originalPreviewImageFileUri)
                                                      .readAsBytesSync(),
                                                  gaplessPlayback: true,
                                                )
                                              : null),
                                    ),
                                  ));
                            })
                            .values
                            .toList()),
                  )),
              Spacer(),
              Container(
                decoration: BoxDecoration(
                    color: Colors.white,
                    border: Border(top: BorderSide(color: Colors.black12))),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: <Widget>[
                    FlatButton(
                      onPressed: () async => await widget.bloc
                          .cropNotePicture(reorderableManager.notePictures,
                              _pageController.page.round())
                          .then((notePictures) {
                        reorderableManager.updateNotePictures(notePictures);
                        reorderableManager
                            .getSmallImagesWidth(notePictures, context)
                            .then((imagesWidth) {
                          smallImagesWidth = imagesWidth;
                        });
                      }),
                      child: Column(
                        children: <Widget>[
                          Icon(
                            Icons.crop,
                            color: Colors.blueAccent,
                          ),
                          Container(
                            margin: EdgeInsets.only(top: 1),
                            child: Text(
                              '裁切',
                              style: TextStyle(color: Colors.blueAccent),
                            ),
                          )
                        ],
                      ),
                    ),
                    FlatButton(
                      onPressed: () {
                        int deleteIndex = _pageController.page.round();
                        widget.bloc
                            .deletePicture(
                                reorderableManager.notePictures, deleteIndex)
                            .then((notePictures) {
                          if (deleteIndex == notePictures.length) {
                            reorderableManager
                                .updateCurrentIndex(notePictures.length - 1);
                          }
                          reorderableManager.updateNotePictures(notePictures);
                          reorderableManager
                              .getSmallImagesWidth(notePictures, context)
                              .then((imagesWidth) {
                            smallImagesWidth = imagesWidth;
                          });

                          if (reorderableManager.notePictures.length == 0) {
                            Navigator.pop(context);
                          }
                        });
                      },
                      child: Column(
                        children: <Widget>[
                          Icon(
                            Icons.delete_outline,
                            color: Colors.blueAccent,
                          ),
                          Container(
                            margin: EdgeInsets.only(top: 1),
                            child: Text(
                              '刪除',
                              style: TextStyle(color: Colors.blueAccent),
                            ),
                          ),
                        ],
                      ),
                    )
                  ],
                ),
              )
            ],
          )),
    );
  }
}
class NotePicturesEditScreen扩展StatefulWidget{
最后的图片列表;
最后说明图片编辑集团;
NotePicturesEditScreen({@required this.notePictures,@required this.bloc});
静态小部件创建(BuildContext上下文、列表notePictures){
返回提供者(
create:(context)=>NotePicturesEditBloc(),
儿童:消费者(
构建者:(上下文、集团)=>
变更通知提供者(
创建:(上下文)=>ReorderableListviewManager(),
孩子:NotePicturesEditScreen(
集团:集团,,
notePictures:notePictures,
),
)),
dispose:(上下文,bloc)=>bloc.dispose(),
);
}
@凌驾
_NotePicturesEditScreenState createState()=>\u NotePicturesEditScreenState();
}
类_NotePicturesEditScreenState扩展状态{
Preload pageController _pageController;
ScrollController ReorderableCollController;
列表说明图片复制;
int-longPressIndex;
列出smallImagesWidth;
双滚动偏移=0;
_reorderableScrollListener(){
scrollOffset=\u reorderableScrollController.offset;
}
@凌驾
void initState(){
Provider.of(上下文,侦听:false)
.notePictures=widget.notePictures;
notePicturesCopy=widget.notePictures;
_reorderableScrollController=ScrollController();
_pageController=预加载pageController();
_redorederableScrollController.addListener(_redorederableScrollListener);
Provider.of(上下文,侦听:false)
.getSmallImagesWidth(注意图片复制,上下文)
.然后((imagesWidth){
smallImagesWidth=imagesWidth;
});
super.initState();
}
@凌驾
无效处置(){
_pageController.dispose();
_reorderableScrollController.dispose();
super.dispose();
}
@凌驾
小部件构建(构建上下文){
ReorderableListviewManager reorderableManager=
Provider.of(上下文,listen:false);
返回安全区(
孩子:脚手架(
appBar:appBar(
背景颜色:Colors.white,
形状:边框(底部:BorderSide(颜色:Colors.black12)),
iconTheme:IconThemeData(颜色:Colors.black87),
海拔:0,
自动嵌入:false,
标题间距:0,
标题:对,
标题:世界其他地区(
mainAxisAlignment:mainAxisAlignment.start,
crossAxisAlignment:crossAxisAlignment.center,
儿童:[
容器(
孩子:我的钮扣(
填充:仅限边缘设置(左:20,右:12),
onPressed:()=>Navigator.of(context.pop(),
图标:图标(Icons.close),
),
),
文本('編輯',
样式:TextStyle(颜色:Colors.black87,字体大小:18))
],
),
行动:[
扁平按钮(
按下:(){},
子:文本(
'下一步',
),
)
],
),
背景颜色:颜色(0xffeeee),
正文:专栏(
mainAxisAlignment:mainAxisAlignment.start,
crossAxisAlignment:crossAxisAlignment.start,
儿童:[
垫片(),
StreamBuilder(
initialData:widget.notePictures,
流:widget.bloc.NotePictureStream,
生成器:(上下文,快照){
notePicturesCopy=snapshot.data;
返回容器(
边缘:边缘组。对称(水平:20),
高度:MediaQuery.of(上下文).size.height*0.65,
子项:Preload PageView.builder(
Preload PageScont:snapshot.data.length,
控制器:_pageController,
itemCount:snapshot.data.length,
onPageChanged:(索引){
reorderableManager.updateCurrentIndex(索引);
reorderableManager.scrollToCenter(
smallImagesWidth,
指数
滚动偏移,
_可再减额滚动控制器,
上下文);
},
itemBuilder:(上下文,索引){
返回容器(
孩子:图像。记忆(
File.fromUri(
snapshot.data[index].polygon.isNotEmpty
?快照数据[索引]
.documentPreviewImageFileUri
:snapshot.data[索引]
.originalPreviewImageFileUri)
.readAsBytesSync(),
无间隙