鍍金池/ 教程/ Java/ 步驟 6:從 JSON 編碼的文件里讀取名字
步驟 1:運(yùn)行一個(gè)框架應(yīng)用
下面要做什么?
總結(jié)和資源
步驟 0:環(huán)境搭建
步驟 5:保存到本地存儲(chǔ)
步驟 7:構(gòu)建并運(yùn)行 App
步驟 2:添加一個(gè)輸入框
步驟 6:從 JSON 編碼的文件里讀取名字
步驟 4:創(chuàng)建一個(gè) PirateName 的類(lèi)
步驟 3:添加一個(gè)按鈕

步驟 6:從 JSON 編碼的文件里讀取名字

在這一步中,你需要更改 PirateName 類(lèi)以實(shí)現(xiàn)從 JSON 文件中獲取名字的列表。這將給你機(jī)會(huì)添加更多的名字進(jìn)程序。

創(chuàng)建 piratenames.json

使用File > New File… 創(chuàng)建一個(gè)名為 piratenames.json 含有以下內(nèi)容的 JSON 編碼的文件。 把文件放在 1-blankbadge 你以前寫(xiě)過(guò)的 Dart 和 HTML 文件的旁邊。

{ "names": [ "Anne", "Bette", "Cate", "Dawn",
        "Elise", "Faye", "Ginger", "Harriot",
        "Izzy", "Jane", "Kaye", "Liz",
        "Maria", "Nell", "Olive", "Pat",
        "Queenie", "Rae", "Sal", "Tam",
        "Uma", "Violet", "Wilma", "Xana",
        "Yvonne", "Zelda",
        "Abe", "Billy", "Caleb", "Davie",
        "Eb", "Frank", "Gabe", "House",
        "Icarus", "Jack", "Kurt", "Larry",
        "Mike", "Nolan", "Oliver", "Pat",
        "Quib", "Roy", "Sal", "Tom",
        "Ube", "Val", "Walt", "Xavier",
        "Yvan", "Zeb"],
  "appellations": [ "Awesome", "Captain",
        "Even", "Fighter", "Great", "Hearty",
        "Jackal", "King", "Lord",
        "Mighty", "Noble", "Old", "Powerful",
        "Quick", "Red", "Stalwart", "Tank",
        "Ultimate", "Vicious", "Wily", "aXe", "Young",
        "Brave", "Eager",
        "Kind", "Sandy",
        "Xeric", "Yellow", "Zesty"]}

關(guān)鍵信息

  • 文件包含 JSON 編碼的 map ,它包含兩個(gè)字符串列表。

編輯 piratebadge.html

顯示輸入框和按鈕

...
  <div>
    <input type="text" id="inputName" maxlength="15" disabled>
  </div>
  <div>
    <button id="generateButton" disabled>Aye! Gimme a name!</button>
  </div>
...
  • Dart 代碼啟用輸入框和按鈕,然后名字成功從 JSON 文件中讀出來(lái)。

編輯 piratebadge.dart

在文件頂部添加一個(gè) import

import 'dart:html';
import 'dart:math' show Random;
import 'dart:convert' show JSON;

import 'dart:async' show Future;
  • dart:async 庫(kù)提供異步編程。
  • Future 提供一個(gè)方式在將來(lái)得到一個(gè)值。(對(duì)于 JavaScript 開(kāi)發(fā)者:Futures 和 Promises 一樣。)

namesappellations 替換成這些靜態(tài)的,空的列表。

class PirateName {
  ...
  static List<String> names = [];
  static List<String> appellations = [];
  ...
}
  • 記得從這些聲明中移除 final 。

  • [ ] 相當(dāng)于 new List() 。

  • List 是一個(gè)通用的類(lèi)型- List 可以包含任何類(lèi)型的對(duì)象。如果你打算讓一個(gè)列表只包含字符串,你可以把它聲明成為 List<String> 。

添加兩個(gè)靜態(tài)的方法到 PirateName 類(lèi):

class PirateName {
  ...

  static Future readyThePirates() async {
    String path = 'piratenames.json';
    String jsonString = await HttpRequest.getString(path);
    _parsePirateNamesFromJSON(jsonString);
  }

  static _parsePirateNamesFromJSON(String jsonString) {
    Map pirateNames = JSON.decode(jsonString);
    names = pirateNames['names'];
    appellations = pirateNames['appellations'];
  }
}
  • readyThePiratesasync 關(guān)鍵字標(biāo)記。一個(gè)異步的方法立即返回一個(gè) Future ,所以調(diào)用者在等待方法完成時(shí)有機(jī)會(huì)做其他事。

  • HttpRequest 用來(lái)檢索來(lái)自 URL 的數(shù)據(jù)時(shí)使用的。

  • getString() 是一個(gè)方便的方法做一個(gè)簡(jiǎn)單的 GET 請(qǐng)求并返回字符串。

  • getString() 是異步的,它建立了一個(gè) GET 請(qǐng)求,當(dāng)完成 GET 請(qǐng)求的時(shí)候返回一個(gè) Future。

  • await 表達(dá)式,你只可以在異步的方法里使用。執(zhí)行暫停直到 GET 請(qǐng)求完成。(當(dāng) FuturegetString() 完成時(shí)返回)
  • GET 請(qǐng)求返回 JSON 字符串之后,代碼從字符串中提取私有名字和稱(chēng)謂。

添加一個(gè)頂級(jí)變量

SpanElement badgeNameElement;

void main() {
  ...
}
  • 存儲(chǔ) span 元素以便重復(fù)使用,而不是從 DOM 里重復(fù)查詢它。

對(duì) main() 函數(shù)做這些更改

void main() {
  InputElement inputField = querySelector('#inputName');
  inputField.onInput.listen(updateBadge);
  genButton = querySelector('#generateButton');
  genButton.onClick.listen(generateBadge);

  badgeNameElement = querySelector('#badgeName');
  ...
}
  • 在全局變量存儲(chǔ)這些 span 元素,同時(shí)在局部變量里存儲(chǔ) input 元素。

然后添加代碼獲得 JSON 文件里面的名字,同時(shí)處理好異常。

main() async {
  ...

  try {
    await PirateName.readyThePirates();
    //on success
    inputField.disabled = false; //enable
    genButton.disabled = false; //enable
    setBadgeName(getBadgeNameFromStorage());
  } catch (arrr) {
    print('Error initializing pirate names: $arrr');
    badgeNameElement.text = 'Arrr! No names.';
  }
}
  • async 修飾方法體,這樣方法就可以 async 關(guān)鍵字了。去除 voidmain 返回值。異步方法必須返回一個(gè)將來(lái),所以你可以指定返回類(lèi)型或讓它空白的。
  • 調(diào)用 readyThePirates() 方法,立即返回一個(gè) Future 。
  • 使用 await 關(guān)鍵字執(zhí)行暫停直到將來(lái)完成。
  • 當(dāng) 將來(lái)通過(guò) readyThePirates() 成功完成返回,設(shè)置界面。
  • 使用 trycatch 來(lái)檢測(cè)和處理錯(cuò)誤。

運(yùn)行應(yīng)用

通過(guò) File > Save All 保存文件。

運(yùn)行應(yīng)用通過(guò)正確點(diǎn)擊 piratebadge.html,選擇 Run in Dartium

如果你想看到應(yīng)用找不到 .json 文件發(fā)生什么,在代碼里改變文件的名字并重新運(yùn)行這個(gè)程序。 把你的應(yīng)用和下面的最終版本對(duì)比一下

http://wiki.jikexueyuan.com/project/learn-dart-in-minutes/images/dart1-learn-dart-in-minutes-step-6-run-the-skeleton-app-pic1.png" alt="dart4" />