Networking
http
패키지와 shared_preferences
패키지를 설치합니다. <latest_version>
은 패키지 문서를 확인해주세요.
dependencies:
http: <latest_version>
shared_preferences: <latest_version>
콘솔에서 실행합니다.
$ flutter pub get
import 합니다.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
Auth token을 얻고 API 호출
initState()
에서 SharedPreferences에서 token을 찾아보고 없으면 token을 받아서 저장합니다. token을 사용하여 API를 호출합니다.
@override
void initState() {
super.initState();
_loadQuizzes();
}
_loadQuizzes() async {
final prefs = await SharedPreferences.getInstance();
String authToken = prefs.getString('token') ?? null;
if (authToken == null) {
String token = await getAuthToken();
authToken = token;
prefs.setString('token', token);
}
_quizzes = getQuizzes(authToken);
setState(() {});
}
API 구현 예제:
Future<List<Quiz>> getQuizzes(token) async {
final response = await http.get(
'https://myquiz.test/quizzes',
headers: {
"Content-type": "application/json",
"Accept": "application/json",
"Authorization": "Bearer $token",
},
);
if (response.statusCode == 200) {
List responseList = json.decode(response.body);
return responseList.map((data) => Quiz.fromJson(data)).toList();
} else {
throw Exception('Failed to load quizzes');
}
}
HTTP status code를 확인하는 부분을 다음처럼 수정하면 201 Created 같은 상태 코드에서 예외가 나는 것을 피할 수 있습니다.
if (response.statusCode >= 200 && response.statusCode < 300) {
}
FutureBuilder
를 사용하여 API 호출 후 결과를 받으면 화면을 다시 만들도록 구현.
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Go back!")),
body: FutureBuilder<List<Quiz>>(
future: _quizzes,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasData) {
return ListView.builder(
// ...
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
}
return Center(
child: CircularProgressIndicator(),
);
},
),
);
}
API 호출결과 hasError가 true면 다른 작업이 필요할 수 있습니다. 아래의 예제는 API 호출 후 권한이 없다는 에러 발생 시, Login 화면으로 이동하는 코드입니다.
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Go back!")),
body: FutureBuilder<List<Quiz>>(
future: _quizzes,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
// 401에러 발생 시 LoginView로 이동
SchedulerBinding.instance.addPostFrameCallback((_) {
Navigator.pushReplacement(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) =>
LoginView(),
),
);
});
return Container();
}
여기서 주의할 점은 API 호출결과를 build()
안에서 처리하고 있기 때문에, build()
가 끝나기 전에 네비게이션을 바꾸면 에러가 발생한다는 점입니다. 이런 코드를 작성해야 하는 경우 SchedulerBinding.instance.addPostFrameCallback() 을 사용하여 네비게이션 변경 작업을 지연시키면 됩니다.