颤振避免多次运行FutureBuilder

时间:2019-12-03 11:40:05

标签: flutter

不幸的是,在我作为新屏幕的简单代码中,FutureBuilder可以正常工作并且两次从方法中获取数据!

我不确定出现什么问题以及如何避免该问题

class LessonDetail extends StatefulWidget {
  final String monthKey;
  final String lessonFileKey;

  LessonDetail({@required this.monthKey, @required this.lessonFileKey});

  @override
  State<StatefulWidget> createState() {
    return _LessonDetailState(monthKey, lessonFileKey);
  }
}

class _LessonDetailState extends BaseState<LessonDetail> {
  String monthKey;
  String lessonFileKey;

  _LessonDetailState(this.monthKey, this.lessonFileKey);


  @override
  Widget build(BuildContext context) {
    return Directionality(
      textDirection: TextDirection.rtl,
      child: Scaffold(
        body: FutureBuilder(
            future: _getLessonDetail(),
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                PlayLessonResponse response = snapshot.data;
                print(response);
              }

              return Center(
                child: CircularProgressIndicator(),
              );
            }),
      ),
    );
  }

  Future<PlayLessonResponse> _getLessonDetail() async {

    AudioList audioList = AudioList(
      'http://www.sample.com',
      'aaaaa'
    );
    List<AudioList> lst = [audioList,audioList,audioList];

    PlayLessonResponse response = PlayLessonResponse(
        2,
        '',
        'http://www.sample.com',
        '2',
        lst,
        1,
        'ssss'
    );


    print('++++++++++++++++++++');
    return response;
  }
}

BaseState类的内容:

abstract class BaseState<T extends StatefulWidget> extends State {
  final Connectivity _connectivity = Connectivity();

  StreamSubscription<ConnectivityResult> _connectivitySubscription;
  bool isOnline = true;
  Future<void> initConnectivity() async {
    try {
      await _connectivity.checkConnectivity();
    } on PlatformException catch (e) {
      print(e.toString());
    }
    if (!mounted) {
      return;
    }

    await _updateConnectionStatus().then((bool isConnected){
      if(mounted){
        setState(() {
          isOnline = isConnected;
        });
      }
    });
  }

  @override
  void initState() {
    super.initState();
    initConnectivity();
    _connectivitySubscription = Connectivity()
        .onConnectivityChanged
        .listen((ConnectivityResult result) async {
      await _updateConnectionStatus().then((bool isConnected){
        if(mounted){
          setState(() {
            isOnline = isConnected;
          });
        }
      });
    });
  }

  @override
  void dispose() {
    _connectivitySubscription.cancel();
    super.dispose();
  }

  Future<bool> _updateConnectionStatus() async {
    bool isConnected;
    try {
      final List<InternetAddress> result =
      await InternetAddress.lookup('google.com');
      if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
        isConnected = true;
      }
    } on SocketException catch (_) {
      isConnected = false;
      return false;
    }
    return isConnected;
  }
}

输出:

I/flutter (32289): ++++++++++++++++++++
I/flutter (32289): ++++++++++++++++++++

1 个答案:

答案 0 :(得分:0)

就像@Ricardo所说的那样,您不应直接在FutureBuilder的future方法内部调用该函数。

相反,您应该首先在init状态下运行函数,并将响应存储在新变量中。只有这样,才能将变量分配给FutureBuilder的未来。

代码示例:

class LessonDetail extends StatefulWidget {
  final String monthKey;
  final String lessonFileKey;

  LessonDetail({@required this.monthKey, @required this.lessonFileKey});

  @override
  State<StatefulWidget> createState() {
    return _LessonDetailState(monthKey, lessonFileKey);
  }
}

class _LessonDetailState extends BaseState<LessonDetail> {
  String monthKey;
  String lessonFileKey;
  Future<PlayLesssonResponse> _myResponse; //added this line

  _LessonDetailState(this.monthKey, this.lessonFileKey);

 @override
  void initState() {
    _myResponse = _getLessonDetail();  // added this line
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Directionality(
      textDirection: TextDirection.rtl,
      child: Scaffold(
        body: FutureBuilder(
            future: _myResponse,  //use _myResponse variable here
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                PlayLessonResponse response = snapshot.data;
                print(response);
              }

              return Center(
                child: CircularProgressIndicator(),
              );
            }),
      ),
    );
  }

  Future<PlayLessonResponse> _getLessonDetail() async {

    AudioList audioList = AudioList(
      'http://www.sample.com',
      'aaaaa'
    );
    List<AudioList> lst = [audioList,audioList,audioList];

    PlayLessonResponse response = PlayLessonResponse(
        2,
        '',
        'http://www.sample.com',
        '2',
        lst,
        1,
        'ssss'
    );


    print('++++++++++++++++++++');
    return response;
  }
}