该功能在页面导航中仅被调用一次

问题描述

我正在尝试编写一个页面,该页面从firebase存储文件夹下载图像并将其显示在网格中。第一次导航到此页面时,我对此没有任何问题。但是,一旦我导航到另一个页面然后又返回到该页面,图像将不再加载。函数getimage()是加载图像的工具。它在initState()中被调用。是因为页面第一次打开时仅被调用一次?

以下是页面导航的代码段:

class RouteGenerator {
  static Route<dynamic> generateRoute(RouteSettings settings) {
    // Getting arguments passed in while calling Navigator.pushNamed
    final args = settings.arguments;

    switch (settings.name) {
...
 case '/stichpage':
        // Validation of correct data type
        return MaterialPageRoute(
          builder: (_) => ImagesScreen(),);
...  
}

这是页面的实际代码

import 'package:Flutter/material.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'dart:typed_data';
import 'dataholder.dart';

class ImagesScreen extends StatelessWidget {
  Widget makeImagesGrid() {
    return GridView.builder(
        itemCount: "objectname".length,gridDelegate:
            SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),itemBuilder: (context,index) {
          return ImageGridItem(index);
        });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.lightBlue,elevation: 5,title: Text('Image Stitching'),centerTitle: true,),body: Container(
        child: makeImagesGrid(),bottomNavigationBar: BottomAppBar(
        color: Colors.grey[200],child: Row(
          children: [
            Spacer(),IconButton(icon: Icon(Icons.save),onpressed: () {}),],floatingActionButton: FloatingActionButton.extended(
        backgroundColor: Colors.lightBlue,foregroundColor: Colors.white,onpressed: () {},icon: Icon(Icons.burst_mode),label: Text('Stitch'),floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,);
  }
}

class ImageGridItem extends StatefulWidget {
  int _index;

  ImageGridItem(int index) {
    this._index = index;
  }

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

class _ImageGridItemState extends State<ImageGridItem> {
  Uint8List imageFile;
  StorageReference photosReference =
      FirebaseStorage.instance.ref().child("images");

  getimage() {
    if (!requestedindexes.contains(widget._index)) {
      int maxSize = 7 * 1024 * 1024;
      photosReference
          .child("cell${widget._index}.png")
          .getData(maxSize)
          .then((data) {
        this.setState(() {
          imageFile = data;
        });
        imageData.putIfAbsent(widget._index,() {
          return data;
        });
      }).catchError((error) {
        debugPrint(error.toString());
      });
      requestedindexes.add(widget._index);
    }
  }

  Widget decideGridTileWidget() {
    if (imageFile == null) {
      return Center(child: Text(""));
    } else {
      return Image.memory(
        imageFile,fit: BoxFit.cover,);
    }
  }

   @override
  void initState() {
    super.initState();
    if (!imageData.containsKey(widget._index)) {
      getimage();
    } else {
      this.setState(() {
        imageFile = imageData[widget._index];
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return GridTile(child: decideGridTileWidget());
  }
}

还有保存图像数据的代码

import 'dart:typed_data';

Map<int,Uint8List> imageData = {};

List<int> requestedindexes = [];

解决方法

当您推送到另一个视图时,先前的视图将保留在Navigator中,因此当您弹出该视图时,它确实会重建,但不会再次调用initState

如果您想在弹出屏幕后又回到主屏幕时实际进行操作,则需要实施RouteObserver,例如

final RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();

class MyApp extends StatelessWidget {

    @override
    Widget build(BuildContext context) {
        return MaterialApp(
            theme: ThemeData(),navigatorObservers: [routeObserver],home: Screen1(),routes: {
                'screen2': (context) => Screen2(),'screen3': (context) => Screen3(),},);
     }
}

一旦您将其设置为主要内容,就需要屏幕为RouteAware

class Screen3 extends StatefulWidget {
    @override
    _Screen3State createState() => _Screen3State(); 
}

class _Screen3State extends State<Screen3> with RouteAware {
    @override
    void didChangeDependencies() {
        super.didChangeDependencies();
        RouteObserverProvider.of(context).subscribe(this,ModalRoute.of(context));
     }

     @override
     void dispose() {
         RouteObserverProvider.of(context).unsubscribe(this);
         super.dispose();
     }

     @override
     void didPush() {
         print('didPush Screen3');
     }

     @override
     void didPopNext() {
         print('didPopNext Screen3');
     }
}

您实际需要的是didPopNext

David Anaya在Medium中有一篇不错的文章,您可以寻找here