フラッタにおけるレトロフィットとXMLの操作
フラッタにおけるレトロフィットとXMLの操作
まもなく、私はこの問題に対する答えを探していました.IOSの背景から来て、私は本当にレトロフィットやライブラリの他のコードジェネレータのようなライブラリにあまりにもされていない.
いずれにしても、それは私が探していた情報を見つけるのが少し難しかったです、そして、私がそれについてポストすることに決めた理由です.
何?
これはレトロフィットかDIOについてのポストではありません、私は簡潔に概念を説明します、しかし、このライブラリを説明しているかなり良いポストがすでにあります.
そうですか?
私たちは何をしていますか。
我々は、我々は停止7602に到着する次のバスを取得するSmart Dublin 🇮🇪APIに当っている小さなサンプルアプリケーションを構築します.実際の製品では、我々は任意の停止をクエリすることができますので、我々のアプリケーションを構築するが、我々のサンプルについては、この停止番号の情報を取得します.
これは、私たちがフェッチするエンドポイントです.
あなたは、ポストの最後に完全なプロジェクトを見つけるが、あなたが沿って続くようにしたい場合は、新しいフラッターアプリを作成することによって起動します.
ヒア プロジェクト構造
まず、ファイル構造を作成します.ダート到着.ダートとSmartRangeダブリン.スクリーンショットのようにダーツファイル.
プロジェクトの構成
依存
いくつかの依存関係やdevdepend依存関係を追加する必要がありますが、一般的な行では以下のようになります:
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^0.1.3
retrofit: ^1.3.4
xml: ^3.5.0
xml2json: ^4.2.0
dev_dependencies:
flutter_test:
sdk: flutter
retrofit_generator: ^1.3.7
build_runner: ^1.10.0
念のため、これを書いた時点で、フラッタ1.21.0 - 10.0を使用しています.プレ18とダーツ2.10 .我々の最初のレトロフィットネットワーク要求
SmartSumダブリンを開けて始めよう.我々のレトロフィットスケルトンを書き留めて、書いてください:
*import *'package:retrofit_xml_sample_app/models/stop.dart';
*import *'package:dio/dio.dart';
*import *'package:retrofit/retrofit.dart';
*part *'smart_dublin.g.dart';
@RestApi(baseUrl: "https://data.smartdublin.ie/cgi-bin/rtpi/")
*abstract class *SmartDublinClient {
*factory *SmartDublinClient(Dio dio, {String baseUrl}) {
*return *_SmartDublinClient(dio, baseUrl: baseUrl);
}
@GET("/realtimebusinformation?format=xml")
@DioResponseType(ResponseType.plain)
Future<Stop> getStopInformation(@Query("stopid") String stopId);
}
上のコードではいくつかのことが起こります.いずれにせよ、このように見えるレトロフィットを使用する方法に関する多くの例があります.また、インターセプターと呼ばれるものの使用を見つけるでしょう.我々がポストの冒頭で言及したように、インターセプターは我々が彼らにどんな操作も行うことができるように、要求と応答を捕えます.
インターセプターで何かできることは、デバッグモードになっている間にコンソールで全てのレスポンスを出力することです(ネットワーク操作をすばやくデバッグするのに非常に便利です).このような場合は、リターン文の右側にある工場本体に以下を追加する必要があります.
dio.interceptors.add(LogInterceptor(requestBody: *true*, responseBody: *true*));
インターセプターは特に私たちのユースケースで興味深いです.なぜなら、XMLを返すネットワークリクエストを実行しているときには、応答を傍受し、JSONファイルに変換して動作させることができます.次のインターセプターでこれを行うことができます.dio.interceptors.add(InterceptorsWrapper(
onResponse: (Response response) *async *{
response.data = Utils.*decodeXmlResponseIntoJson*(response.data);
*return *response;
},
));
ここに追加の手順があり、utilsファイルを作成したのですが、utils/mainを作成するためには、utilsファイルを作成しました.dartファイルをペーストします.*import *'dart:convert';
*import *'package:xml2json/xml2json.dart';
*const *kQuoteReplacer = "¿*¿*¿*¿*";
*class *Utils {
*static dynamic decodeXmlResponseIntoJson*(String data) {
String cleanDataString = data.replaceAll(""", kQuoteReplacer);
*final *Xml2Json transformer = Xml2Json();
transformer.parse(cleanDataString);
*final *json = transformer.toGData();
*return *jsonDecode(json);
}
}
Xml 2 JSONライブラリから別のJSONトランスフォーマーを使用できます.私はgdataをより良いこの変換のための私に合うものを見つけたが、それはあなたのユースケースの場合ではない可能性がありますので、いくつかの他の変圧器を確認してください.モデル
私たちのレトロフィットコードがSTOPと呼ばれるモデルを使用していることに気づいたかもしれません.これは私たちのネットワークのリクエストの応答をすぐに我々の停止モデル、かなり便利なオブジェクトに変換されているためです!
このモデルは、「Fromjson」メソッドをレトロフィットで動作するようにするだけです.
ストップモデルをストップにコピーしましょう.ダート
*import *'package:retrofit_xml_sample_app/models/arrival.dart';
*class *Stop {
*final *List<Arrival> arrivals;
*final *String stopId;
Stop({
*this*.arrivals = *const *[],
*this*.stopId,
});
*factory *Stop.fromJson(Map<String, *dynamic*> jsonMap) {
*final *stopId = jsonMap['realtimeinformation']['stopid']['\$t'];
*final *List<Arrival> arrivalsList = [];
*final *results = jsonMap['realtimeinformation']['results']['result'];
*if *(results != *null*) {
*for *(*var *result *in *results) {
arrivalsList.add(Arrival.fromJson(result));
}
}
*return *Stop(
arrivals: arrivalsList,
stopId: stopId,
);
}
@override
String toString() {
*return *'Stop { stopId: $stopId, arrivals: ${arrivals.length} }';
}
}
ファクトリメソッドは、レスポンスから値を持つオブジェクトを充填する担当者です.これは基本的にモデルへの応答を解析します.私がこの例のクラスをモデル化した方法は、ストップが到着のリストを持っているということです.到着モデルのコードは次のようになります.
*class *Arrival {
*final *String route;
*final *String origin;
*final *String destination;
*final *String dueTime;
Arrival({
*this*.route,
*this*.origin,
*this*.destination,
*this*.dueTime,
});
*factory *Arrival.fromJson(Map<String, *dynamic*> jsonMap) {
*final *route = jsonMap['route']['\$t'];
*final *origin = jsonMap['origin']['\$t'];
*final *destination = jsonMap['destination']['\$t'];
*final *dueTime = jsonMap['duetime']['\$t'];
*return *Arrival(
route: route,
origin: origin,
destination: destination,
dueTime: dueTime,
);
}
@override
String toString() {
*return *'Arrival { route: $route }';
}
}
自動生成
今、我々は、我々が以前に見たG . Dartファイルを自動生成することができます.
そのためには、プロジェクトフォルダ内の端末でこれを実行してください.
flutter pub run build_runner build
そうした後に、新しい自動生成されたファイルSmartSumダブリンを見るべきです.G . DARTによる手法の実装このファイルを既に実行していて、以前に自動生成されたファイルを上書きする必要がある場合は、build - rangerコマンドに- delete -競合する出力フラグを追加することができます.
flutter pub run build_runner build --delete-conflicting-outputs
すべてをまとめる
私たちの新しいレトロフィット方法を実際に使う時です.最初にUIをビルドする必要があります.ちょうどこれを維持するために、私はメインで一緒にすべてのUIを結びました.ダートファイル.
MyAppのステイタスウィジェットが必要になります.
*import *'package:flutter/material.dart';
*import *'package:retrofit_xml_sample_app/api/smart_dublin.dart';
*import *'package:retrofit_xml_sample_app/models/stop.dart';
*import *'package:dio/dio.dart';
*const *kStopId = '7602';
*void *main() {
runApp(MyApp());
}
*class *MyApp *extends *StatelessWidget {
@override
Widget build(BuildContext context) {
*return *MaterialApp(
title: 'Bus stop info',
theme: ThemeData(
primarySwatch: Colors.*blue*,
visualDensity: VisualDensity.*adaptivePlatformDensity*,
),
home: MyHomePage(),
);
}
}
*class *MyHomePage *extends *StatefulWidget {
MyHomePage({Key key}) : *super*(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
*class *_MyHomePageState *extends *State<MyHomePage> {
//To complete next
}
次に、我々はCount MyHomePageStatesクラスを満たします.最初に我々の変数、停止を保持する1つ、別の1つは、新しいAPIクライアントを保持します.Stop _stop = Stop(arrivals: [], stopId: kStopId);
*final *_apiClient = SmartDublinClient(Dio());
私たちは、停止モデルのための到着の空のリストをデフォルト値として使用しています.SmartDubleClientクラスのinitメソッドは、新しいdioインスタンスを送信する必要があります.何らかの理由で複数のAPIクライアントを使用している場合は、同じDIOインスタンスを再利用することができます(少なくともこの時点では実際には副作用が発生しません).
我々のAPIクライアントからSTOP情報を要求する新しいメソッドを作成し、このサンプルの状態管理ソリューションとして状態を使用します.
*void *loadStopInformation() *async *{
Stop stop = *await *_apiClient.getStopInformation(kStopId);
setState(() {
_stop = stop;
});
}
とinitstateとbuildのメソッドをオーバーライドします.@override
*void *initState() {
*super*.initState();
loadStopInformation();
}
@override
Widget build(BuildContext context) {
*return *Scaffold(
body: SafeArea(
child: Column(
children: <Widget>[
Padding(
padding: *const *EdgeInsets.all(16.0),
child: Text(
' 🚌 Stop 7602',
style: TextStyle(
fontWeight: FontWeight.*bold*,
fontSize: 32,
),
),
),
Flexible(
child: buildList(),
)
],
),
),
);
}
ビルドメソッド内でBuildListを呼び出していることに気づいたかもしれません.私は、サンプルで明快さのために彼らを分離させました:Widget buildList() {
*if *(_stop.arrivals.isEmpty) {
*return *Text("Sorry, there are no buses anytime soon 🤷🏽♀️");
}
*return *ListView.builder(
itemCount: _stop.arrivals.length,
itemBuilder: (BuildContext context, int index) {
*return *Padding(
padding: *const *EdgeInsets.fromLTRB(16, 8, 16, 8),
child: Container(
height: 40,
decoration: BoxDecoration(
color: Colors.*white*,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.*grey*,
spreadRadius: 1,
offset: Offset(0, 0),
)
],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text("Arriving in ${_stop.arrivals[index].dueTime} mins"),
Text(
"${_stop.arrivals[index].route} to ${_stop.arrivals[index].destination}"),
],
),
),
);
},
);
}
ビルドリストメソッドでは、停止の到着が空で、リストがない場合にメッセージを表示します.一緒にすべてを置いた後、あなたはこのようなものを見るべきです👇🏼
アプリの最終キャプチャ
おめでとう!🥳
あなたがそれを通して作ったうれしい!あなたがポストを楽しんで、道で何かを学ぶという望み.
あなたがちょうどコードにまっすぐに飛び込みたいならば、あなたはそれをここで見つけます👇🏼
私はあなたの考えを知っているし、次に聞いてみたいもの!次のポストを参照してください!👋
Reference
この問題について(フラッタにおけるレトロフィットとXMLの操作), 我々は、より多くの情報をここで見つけました https://dev.to/fray_88/working-with-retrofit-and-xml-on-flutter-4724テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol