【问题标题】:Flutter/Dart : synchronous way to read file in asset folderFlutter/Dart:同步读取资产文件夹中的文件
【发布时间】:2023-03-14 22:47:02
【问题描述】:

我正在尝试读取资产文件夹中的 JSON 文件并将其反序列化为对象。 String fromJson = await rootBundle.loadString('assets/File.json'); 反序列化函数是异步的,因此它甚至在实际读取 JSON 文件并对其进行反序列化之前就返回。这就是为什么从项目的不同位置多次调用此反序列化函数的原因。

所有异步调用在执行第一个等待调用之前排队,即。 await rootBundle.loadString('assets/File.json'); 所以文件被多次读取。

有没有办法等待文件读取或等到反序列化发生然后返回给反序列化函数的调用者?或同步方式读取资产文件夹中的文件? 我希望文件只读取一次并等待反序列化发生。

【问题讨论】:

    标签: file flutter asynchronous dart


    【解决方案1】:

    一般来说,异步读取文件根本不成问题,实际上是推荐的。您不想在等待文件加载和解析时阻塞 UI。

    因此,这意味着您的代码中可能存在导致此问题的小错误。由于您没有列出任何代码,因此我无法真正指出问题所在,但我确实有一个我一直在使用的示例,它可能会对您有所帮助。

    在我的示例应用程序(您可以找到 here)中,我使用以下 JSON 文件(实际文件更大,但这给了您一个想法):

    places.json

    {
        "html_attributions": [],
        "results": [
            {
                "geometry": {
                    "location": {
                        "lat": 52.221525,
                        "lng": 6.895323999999999
                    },
                    "viewport": {
                        "northeast": {
                            "lat": 52.2231135302915,
                            "lng": 6.897867100000001
                        },
                        "southwest": {
                            "lat": 52.2204155697085,
                            "lng": 6.894476299999999
                        }
                    }
                },
                "icon": "https://maps.gstatic.com/mapfiles/place_api/icons/restaurant-71.png",
                "id": "6e274492c5dfc4100a68d47e70d8f69e1bbef40a",
                "name": "Fellini Enschede",
                "opening_hours": {
                    "open_now": true
                },
                "photos": [
                    {
                        "height": 3024,
                        "html_attributions": [
                            "<a href=\"https://maps.google.com/maps/contrib/109213220123895357242/photos\">Martijn Hoppenbrouwer</a>"
                        ],
                        "photo_reference": "CmRaAAAAPhSAiB4-VuS-AmUdRxjBUIooQJg68zdQyLRmPJGOB7G_2xh9deq3lcI9ChPnlaTZPmQtUQ_uBqWenNLif0Okqqr5ErAGPBlhoIpcbW6iBt0Uto1qjOjRPuWTRrrL_imlEhDjC25hFY3jKzMU04ZbXUaqGhQh13kxVLaYj-aNxDnsqWfRvfWFBA",
                        "width": 4032
                    }
                ],
                "place_id": "ChIJ8XcydnMUuEcRCFdOhmTnLsY",
                "plus_code": {
                    "compound_code": "6VCW+J4 Enschede, Netherlands",
                    "global_code": "9F486VCW+J4"
                },
                "rating": 4.1,
                "reference": "CmRSAAAAtmshr7ZCjO5X5Zb8ZHNGgek6CzPUBXHBEtP7AR_A8vg10GMpcMCdk_S1Y141Nv5G3f7ed9XFPaSjU6aR_lHoJ6PwNx3lQL7HJf9ai9G2aExbs5KHuwacwTqUV3ocI1RkEhDWe_4cklgqwe94iyEOg4fNGhSZL88S4ZAde2kWm0VAwm8gObCCjg",
                "scope": "GOOGLE",
                "types": [
                    "night_club",
                    "bar",
                    "restaurant",
                    "food",
                    "point_of_interest",
                    "establishment"
                ],
                "vicinity": "2, Bolwerkstraat, Enschede"
            },
            {
                "geometry": {
                    "location": {
                        "lat": 52.22302359999999,
                        "lng": 6.893403099999998
                    },
                    "viewport": {
                        "northeast": {
                            "lat": 52.22446798029149,
                            "lng": 6.894722280291502
                        },
                        "southwest": {
                            "lat": 52.22177001970849,
                            "lng": 6.892024319708497
                        }
                    }
                },
                "icon": "https://maps.gstatic.com/mapfiles/place_api/icons/generic_business-71.png",
                "id": "a18ff7853e5f6eb545fcb93fd55c85cf915bd301",
                "name": "'T Bölke",
                "photos": [
                    {
                        "height": 1152,
                        "html_attributions": [
                            "<a href=\"https://maps.google.com/maps/contrib/115418315198000399419/photos\">&#39;t Bölke</a>"
                        ],
                        "photo_reference": "CmRaAAAAhRaUOljchj6XFtlC7sB-93l4pfcEMTClAG6pZbPkE4KQ64Y9kPY0cAZ6uozFJdD_aB7BHPfIbhY2EU-47b8v_lWjaZcaQX_YIhh1Hqbz9tMCv-brLfxYzykbpfYMVaa2EhD_9RqnDMDDYjzR_lJvYW_UGhQi4dnTzDTgIiaRHNVrlmfv28qRvw",
                        "width": 2048
                    }
                ],
                "place_id": "ChIJX2MAvHQUuEcRY9HmmyKX1oI",
                "plus_code": {
                    "compound_code": "6VFV+69 Enschede, Netherlands",
                    "global_code": "9F486VFV+69"
                },
                "rating": 4.1,
                "reference": "CmRSAAAAZ-3uQbzsSLjQRshhJ9L6J7iOOMV2T7HL-ELqrufGKXflCbVHaEDD3-eNoAvVsF0k4muHAQT-rQaf-bYPFuy3BafMyLzMnscR1cTuCVwpLvo-Gh9O62PJmhMtSqbcJvoCEhDVHVVCEIxrmEhHY96ucRlHGhTAU1zn9KcPxRsZslAvinU1mBmtSQ",
                "scope": "GOOGLE",
                "types": [
                    "night_club",
                    "bar",
                    "point_of_interest",
                    "establishment"
                ],
                "vicinity": "Molenstraat 6-8, Enschede"
            }
        ]
    }
    

    接下来我有一个帮助 Dart 文件,它定义了 Place 类并包含一个方法,该方法将读取文件并将 JSON 项转换为 Place 类的实例,如下所示:

    places.dart

    import 'dart:async';
    import 'dart:convert';
    
    import 'package:flutter/services.dart';
    
    class Place {
      final String name;
      final double rating;
      final String address;
    
      Place.fromJson(Map jsonMap) : 
        name = jsonMap['name'],
        rating = jsonMap['rating']?.toDouble() ?? -1.0,
        address = jsonMap['vicinity'];
    
      String toString() => 'Club: $name';
    }
    
    Future<Stream<Place>> getPlaces() async {
      return new Stream.fromFuture(rootBundle.loadString('assets/places.json'))
        .transform(json.decoder)
        .expand((jsonBody) => (jsonBody as Map)['results'])
        .map((jsonPlace) => new Place.fromJson(jsonPlace));
    }
    

    最后我有一个非常简单的 UI,它将调用 getPlaces 方法并在 ListView 中显示所有记录:

    ma​​in.dart

    import 'package:flutter/material.dart';
    
    import 'places.dart';
    
    void main() => runApp(new MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          title: 'Slurp',
          theme: new ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: new MyHomePage(title: 'Slurp'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => new _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
    
      List<Place> _places = <Place>[];
    
      @override
      void initState() {
        super.initState();
    
        listenForPlaces();
      }
    
      void listenForPlaces() async {
        var stream = await getPlaces();
    
        stream.listen(
          (place) => 
            setState(
              () => _places.add(place)
            )
          );
      }
    
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
          appBar: new AppBar(
            title: new Text(widget.title),
          ),
          body: new Center(
            child: new ListView(
              children: _places.map((place) => new PlaceWidget(place)).toList(),
            ),
          ),
        );
      }
    }
    
    class PlaceWidget extends StatelessWidget {
      final Place place;
    
      PlaceWidget(this.place);
      
      @override
      Widget build(BuildContext context) {
        var ratingColor = Color.lerp(Colors.red, Colors.green, place.rating / 5);
    
        var listTile = new ListTile(
          leading: new CircleAvatar(
            child: new Text(place.rating.toString()),
            backgroundColor: ratingColor,
          ),
          title: new Text(place.name),
          subtitle: new Text(place.address),
        );
    
        return new Dismissible(
          key: new Key(place.name),
          background: new Container(color: Colors.green),
          secondaryBackground: new Container(color: Colors.red),
          onDismissed: (dir) {
            if(dir == DismissDirection.startToEnd) {
              print("You liked ${place.name}");
            } else {
              print("You didn't like ${place.name}");
            }
          },
          child: listTile,
        );
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-03-03
      • 2023-03-11
      • 1970-01-01
      • 2017-12-02
      • 1970-01-01
      • 1970-01-01
      • 2011-01-22
      • 2021-12-11
      相关资源
      最近更新 更多