2017-08-22 157 views
0

我一直在面對一些與setState函數有關的問題,同時使用有狀態的小部件在定時器的幫助下更新自己。下面的代碼顯示了2個主要的類,它們複製了我如何發現這個錯誤。文本小部件「Lorem」應該在10秒內插入 - 它是 - 但它從未顯示。我試圖調試數組「Items」,它在012秒後會在5秒後包含「lorem」文本小部件,因爲它應該如此。 「構建」功能可以運行,但在界面上沒有任何區別。setState不會更新用戶界面

class textList extends StatefulWidget { 

    @override 
    State<StatefulWidget> createState() => 
     new _textListState(); 
} 

class _textListState extends State<textList> 
    with TickerProviderStateMixin { 

    List<Widget> items = new List(); 
    Widget lorem = new textClass("Lorem"); 
    Timer timer; 

    @override 
    void initState() { 
    super.initState(); 

    items.add(new textClass("test")); 
    items.add(new textClass("test")); 

    timer = new Timer.periodic(new Duration(seconds: 5), (Timer timer) { 
     setState(() { 
     items.removeAt(0); 
     items.add(lorem); 
     }); 
    }); 
    } 

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

    @override 
    Widget build(BuildContext context) { 
    Iterable<Widget> content = ListTile.divideTiles(
     context: context, tiles: items).toList(); 

    return new Column(
     children: content, 
    ); 
    } 
} 

class textClass extends StatefulWidget { 
    textClass(this.word); 

    final String word; 

    @override 
    State<StatefulWidget> createState() => 
     new _textClass(word); 
} 

class _textClass extends State<textClass> 
    with TickerProviderStateMixin { 
    _textClass(this.word); 

    String word; 
    Timer timer; 

    @override 
    void initState() { 
    super.initState(); 

    timer = new Timer.periodic(new Duration(seconds: 2), (Timer timer) { 
     setState(() { 
     word += "t"; 
     }); 
    }); 
    } 

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


    @override 
    Widget build(BuildContext context) { 
    return new Text(word); 
    } 
} 

這不是我怎麼來找到這個錯誤,但這個是複製它的最簡單方法。主要思想是:孩子們的文本應該不斷更新自己(在這種情況下,最後加上「t」),5秒後,最後一個應該替換爲Text Widget「Lorem」,會發生什麼在列表中但不在UI中。

回答

1

這裏的什麼是錯的:

  • 一個State不應該有任何構造函數的參數。使用widget屬性可以訪問關聯的StatefulWidget的最終屬性。
  • 顫振正在重用您的_textClass實例,因爲類名稱和鍵匹配。這是一個問題,因爲您只在initState中設置了widget.word,因此您沒有獲取新的word配置信息。您可以通過給StatefulWidget實例指定唯一的密鑰來消除它們的歧義並解決舊的State問題,或者您可以保留舊的State並實現didUpdateWidget。後一種方法如下所示。

video

import 'dart:async'; 
import 'package:flutter/material.dart'; 

void main() { 
    runApp(new MaterialApp(
    home: new Scaffold(
     appBar: new AppBar(title: new Text('Example App')), 
     body: new textList(), 
    ), 
)); 
} 

class textList extends StatefulWidget { 

    @override 
    State<StatefulWidget> createState() => 
     new _textListState(); 
} 

class _textListState extends State<textList> 
    with TickerProviderStateMixin { 

    List<Widget> items = new List(); 
    Widget lorem = new textClass("Lorem"); 
    Timer timer; 

    @override 
    void initState() { 
    super.initState(); 

    items.add(new textClass("test")); 
    items.add(new textClass("test")); 

    timer = new Timer.periodic(new Duration(seconds: 5), (Timer timer) { 
     setState(() { 
     items.removeAt(0); 
     items.add(lorem); 
     }); 
    }); 
    } 

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

    @override 
    Widget build(BuildContext context) { 
    Iterable<Widget> content = ListTile.divideTiles(
     context: context, tiles: items).toList(); 

    return new Column(
     children: content, 
    ); 
    } 
} 

class textClass extends StatefulWidget { 
    textClass(this.word); 

    final String word; 

    @override 
    State<StatefulWidget> createState() => 
     new _textClass(); 
} 

class _textClass extends State<textClass> 
    with TickerProviderStateMixin { 
    _textClass(); 

    String word; 
    Timer timer; 

    @override 
    void didUpdateWidget(textClass oldWidget) { 
    if (oldWidget.word != widget.word) { 
     word = widget.word; 
    } 
    super.didUpdateWidget(oldWidget); 
    } 

    @override 
    void initState() { 
    super.initState(); 
    word = widget.word; 

    timer = new Timer.periodic(new Duration(seconds: 2), (Timer timer) { 
     setState(() { 
     word += "t"; 
     }); 
    }); 
    } 

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


    @override 
    Widget build(BuildContext context) { 
    return new Text(word); 
    } 
}