简体   繁体   English

Flutter - 提供者 - 如何根据提供者的值更改 UI?

[英]Flutter - Provider - How to change UI based on value from Provider?

I want to have two forms of the UI based on an object value that I get from a Stream Provider.我想要基于从 Stream 提供程序获得的 object 值的 UI 的两个 forms。

In the widget, I get the object like this:在小部件中,我得到这样的 object:

final recentPostData = Provider.of<List<RecentPostData>>(context) ?? [];

Then, I want to change the UI based on an attribute of RecentPostData:然后,我想根据RecentPostData的一个属性来改变UI:

return SingleChildScrollView(
      child: Column(children: [
        (recentPostData[0].attribute != '123') ?
          RaisedButton( ... )
        : SizedBox( ... ),

The problem: There is a delay of the stream value coming in, thus I get the initial error: "RangeError (index): Invalid value: Valid value range is empty: 0"问题: stream 值有延迟,因此我收到初始错误:“RangeError (index): Invalid value: Valid value range is empty: 0”

I tried to therefore use multiple conditions - hence check first (recentPostData,= []) and then check for the second condition.因此,我尝试使用多个条件 - 因此首先检查 (recentPostData,= []),然后检查第二个条件。 but this did not work (got the same error).但这不起作用(得到了同样的错误)。

Do you have any idea how to solve this?你知道如何解决这个问题吗?

Many thanks in advance!提前谢谢了!

class _PostFeedState extends State<PostFeed> {

  bool isLoading = false; // track if products fetching

  @override
  Widget build(BuildContext context) {

  var recentPostData = Provider.of<List<RecentPostData>>(context) ?? [];

  getProducts() async {  
    if (!hasMore) {  
      print('No More Products');  
      return;  
    }  
    if (isLoading) {  
      return;  
    }  
    setState(() {
      isLoading = true; 
    });  
    QuerySnapshot querySnapshot;  
    if (lastDocument == null) {  
      querySnapshot = await firestore
        .collection('posts')  
        .orderBy('timestamp', descending: true)  
        .limit(documentLimit)  
        .getDocuments();  
      print(0);
    } else {  
      querySnapshot = await firestore  
        .collection('posts')  
        .orderBy('timestamp', descending: true)  
        .startAfterDocument(lastDocument)  
        .limit(documentLimit)  
        .getDocuments();  
      print(1);  
    }  
    if (querySnapshot.documents.length < documentLimit) {  
      hasMore = false;  
    }
    if (querySnapshot.documents.length == 0) {
      setState(() {
        hasMore = false;
        isLoading = false;
      }); 

      return;
    } 
    lastDocument = querySnapshot.documents[querySnapshot.documents.length - 1];  
    products.addAll(querySnapshot.documents);  
    setState(() {  
      isLoading = false;  
    });  
  }

  if (init) {
    getProducts();
    setState(() {
      init = false;
    });
  }

  void loadNewPosts() {
    setState(() {
        products = [];
        lastDocument = null;
      });
    getProducts();
  }

  return SingleChildScrollView(
      child: Column(children: [
        (recentPostData != []) ? (recentPostData[0].pid != DatabaseServicePosts().postDataFromSnapshot(products[0]).pid) ?
          RaisedButton(
            onPressed: () {
              loadNewPosts();
              setState(() {
                hasNew = false;
              });
            },
            child: Text('New Posts Available'),
            color: Colors.green[300],
          )
        : SizedBox(height: 0) : SizedBox(height: 0),
        products.length == 0  
          ? Center(  
            child: Text('No Data...'),
          ) :
          Column(children: <Widget>[
            ...products.map((el) => PostTile (postData: DatabaseServicePosts().postDataFromSnapshot(el))),
          ],),
        (hasMore && !init) ?
          RaisedButton(
            onPressed: () {
              getProducts();
            },
            child: Text(
              'More Posts',
              style: TextStyle(color: Colors.white),
            ),
            color: Colors.lightBlue[200],
            shape: RoundedRectangleBorder(
              borderRadius: new BorderRadius.circular(102.0),
              side: BorderSide(color: Colors.blueGrey[400])
            ),
          )
          : Padding(
            padding: const EdgeInsets.all(10.0),
            child: Container(child: Text('No more Posts')),
          ),
        isLoading  
          ? Container(  
              child: Text('Loading'),  
            )  
          : Container(),
        SizedBox(height: 10),
      ]  
    ),
  ); 

  }
}

I think before building widget checking size of recentPostData can solve your issue.我认为在构建小部件之前检查 recentPostData 的大小可以解决您的问题。 Following code may help You.以下代码可能会对您有所帮助。

recentPostData.length > 0 ? (recentPostData[0].attribute != '123') ?
          RaisedButton( ... )
        : SizedBox( ... ) : Text(" show Loading indicator")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM