【问题标题】:Flutter: how to use function result as var in multiple classes without repeating the functionFlutter:如何在多个类中使用函数结果作为var而不重复函数
【发布时间】:2020-03-18 20:32:54
【问题描述】:

我使用多次获取从 API 获取一些页面和相关内容。 这里,getClass()getValue() 从另一个类调用 API,返回未来。

List<dynamic> pIds, ps;
apiStart() async {
  pageIds = new List();
  siteCls = await _baseApi.getClass(siteCName);
  siteCId = siteCls.data.classId.toString();

  pageCls = await _baseApi.getClass(pageCName);
  pageCId = pageCls.data.classId.toString();

  siteIns = await _baseApi.getValue(siteCId);
  pageIns = await _baseApi.getValue(pageCId);

  pageIds = getPageIds();
  pages = getPagesData();
}

List getPageIds() {
  //Doing some work here
  return pIds;
}

List getPagesData() {
  //Doing some work here
  return ps;
}

现在我想从其他/多个类访问变量,如“页面”,而不重复这些函数。我该怎么做?

更新:

这是一个示例代码。它返回“欢迎 test1!”。当我从apiStart() 中删除content = "test1"; 时,返回“welcome h!”。使用await 有什么问题吗?

class AppData {
  factory AppData() {
    return _singleton;
  }
  static final AppData _singleton = AppData._internal();
  AppData._internal() {
    print("Instance created App-Data");
  }

  BaseApi _baseApi = new BaseApi();

  var content = "hi";
  Future body() {
    return Future.value(content);
  }

  void apiStart() async{
    content = "test1";//OK when I put content here 
    print(content);

    _ids = await _baseApi.fetchIds();
    //Does not change when I put content here
    //I need to use await because I need ids for next function
    content = "test2";  
    print(content);

    //Doing some work with result and get ids as list
    List id = idList();

    _pages = await _baseApi.fetchPages(id[0]);
    //Doing some work with result and get page content
    contents = contentList();
  }
}

如果我执行以下操作,它会返回“test2”。但我不知道如何检查工作是否完成;我应该在函数末尾添加一个布尔变量并每秒钟检查一次吗?那效率高吗?

Future body() {
  return Future.delayed(Duration(seconds: 10)).then((value) => content);
}

我在哪里运行单例

void main() {
  runApp(MyApp());
  AppData().apiStart();
}

我这样展示部分结果:

class ContentWidget extends StatefulWidget {
  ContentWidget({Key key}) : super(key: key);

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

class _ContentWidgetState extends State<ContentWidget> {
  Future<dynamic> futureContent;

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

    futureContent = AppData().body();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<dynamic>(
      future: futureContent,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return Text("Welcome ${snapshot.data}!", style: plainTextStyle);
        } else {
          //return Text("Welcome ${snapshot.error}!", style: plainTextStyle);
        }
        // By default, show a loading spinner.
        return CircularProgressIndicator();
      },
    );
  }
}

【问题讨论】:

    标签: flutter dart async-await future


    【解决方案1】:

    您可以使用单例模式来创建服务类:它使您可以从代码中的任何位置访问此类。

    不要过度使用它,因为它可能会变成一个非常混乱的全局变量,如缺乏封装。

    注意:这是一个巨大的简化,但会起作用。阅读 aroudn 单例和服务以了解更多信息。

    class ApiService {
      // next 5 lines is a typical singleton pattern
      static ApiService _singleton;
      factory ApiService() {
        return _singleton ??= new ApiService._internal();
      }
      ApiService._internal();
    
      //here you'll keep your data
      List<dynamic> pageIds, pages; //store your data in these variables
    
      //run this on the beginning of your app to get your data. Don't forget this!
      void apiStart() async {
        // your code here where you hit the API and get all your data,
        // eg methods getPageIdsFromAPI and getPagesDataFromAPI that you need to write. They return your data
        //    pageIds = getPageIdsFromAPI();
        //    pages = getPagesDataFromAPI();
      }
    }
    

    然后,您可以从代码中的任何地方访问此类中的变量和函数

    ApiService().pageIds
    ApiService().pageIds.length
    ApiService().pageIds.contains(some_id)
    

    ---编辑---

    您需要决定等待何时发生。要么在显示屏幕之前等待数据,要么在空白/等待模式下显示屏幕(就像 facebook 那样)然后等待。

    做第二个:

    @override
    void initState() { 
      WidgetsBinding.instance.addPostFrameCallback((_) { 
        futureContent = await AppData().body();
        setState(() { 
          // refresh whatever changed. it's a good practice to specify what 
        });
      });
    }
    

    【讨论】:

    • 非常感谢。我认为这应该是解决方案,但我不知道 API 调用完成后如何使用变量。当我使用 ApiService().pageIds.length 时,它返回 0。我如何检查 var 是否有值?
    • 确保检查 AFTER 您的 API 确实已完成。您可能必须 await 才能返回 API 调用。喜欢pages = await getPagesDataFromAPI();
    • 不能以这种方式工作,或者我不知道在这些函数完成后如何(从其他类)获取值。假设我添加了String p 作为另一个数据并且在apiStart() 的末尾我有p="finished";当我想获取结果时,它也返回 null。
    • 如果没有看到您的代码,我认为我无能为力。也许更新问题,或者分享 github 链接并准确描述它发生的位置?您可能需要阅读 asyncawait - 它们不是简单的概念(我花了很长时间才开始了解它们)。
    • 更新了问题。我认为apiStart() 中的await 会导致问题,但不知道为什么以及我应该怎么做,因为我需要逐行运行该函数,因为我正在使用下一行中的每个数据。
    猜你喜欢
    • 2018-10-08
    • 2018-01-24
    • 1970-01-01
    • 2019-07-31
    • 2017-01-25
    • 1970-01-01
    • 2018-06-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多