簡體   English   中英

調用 SetState() 時,如何避免帶有 UniqueKey 的 Flutter FutureBuilder 閃爍?

[英]How to avoid Flutter FutureBuilder with UniqueKey flickering when SetState() is called?

我有一個PageView (父 PageView),它的每個頁面都是一個返回FutureBuilderStatefulWidget FutureBuilder本身也會返回一個PageView (子 PageView)。 因為我希望父級和子PageView都保留頁面,所以父級和子級小部件都使用AutomaticKeepAliveClientMixin實現。

每個頁面都分配了一個UniqueKey ,因為頁面是動態的,這意味着用戶可以刪除某些頁面或添加頁面。 但是在調用SetState()時,有兩個問題: 1 整個頁面閃爍; 2 子PageView跳回到索引 0 處的頁面。

如果我不使用UniqueKey ,這兩個問題就會消失。 但是添加或刪除頁面后,您無法刷新頁面。

任何建議表示贊賞,謝謝!

顯示閃爍的代碼:

void main() async {
  runApp(
    MaterialApp(
      title: 'Test',
      home: Scaffold(
        body: Bar(),
      ),
    ),
  );
}

class Bar extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _BarState();
}

class _BarState extends State<Bar> {
  List<Widget> pages;

  final controller = PageController(initialPage: 0, keepPage: true);
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    pages = [
      Center(child: PageWithFutureBuilder(key: UniqueKey())),
      Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          PageWithFutureBuilder(key: UniqueKey()),
          RaisedButton(
            onPressed: () {
              refresh();
            },
            child: new Icon(
              Icons.refresh,
              color: Colors.blue,
              size: 30.0,
            ),
          )
        ],
      ),
    ];
    return PageView(
      controller: controller,
      children: pages,
    );
  }

  void refresh() async {
    setState(() {});
  }
}

class PageWithFutureBuilder extends StatefulWidget {
  PageWithFutureBuilder({Key key}) : super(key: key);
  @override
  State<StatefulWidget> createState() => _PageWithFutureBuilderState();
}

Future test() async {
  return;
}

class _PageWithFutureBuilderState extends State<PageWithFutureBuilder> {
  Future future;
  @override
  void initState() {
    future = test();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: future,
      builder: (ocntext, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting)
          return Container(
            color: Colors.black,
            child: Center(child: CircularProgressIndicator()),
          );
        else if (snapshot.connectionState == ConnectionState.done) {
          return Center(child: Text('test text'));
        } else
          return Container();
      },
    );
  }
}

滑動到第二頁,然后單擊按鈕,您會看到閃爍。 至於jumping back to page at index 0的代碼,太復雜了,就不放了,估計和閃爍的原因是一樣的。

我想我找到了正確的解決方案。 基本上是用錯了Key造成的。 使用UniqueKey使 Flutter 將子小部件視為不同,因此每次重建時它都會重新初始化新的子小部件。 因此閃爍並跳回索引 0 處的頁面。

不要使用UniqueKey ,而是使用值鍵。 在我的例子中,我的每個孩子父母都有一個唯一的object ID ,所以我使用Key(objectID)作為鍵。 因此,當調用SetState()時,flutter 將知道某些小部件可以重復使用,因為它們具有相同的鍵,因此閃爍消失並且它不會跳回到索引 0 處的頁面。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM