[플러터] 17. Dio 라이브러리로 통신하기

KangHo Lee's avatar
Dec 31, 2024
[플러터] 17. Dio 라이브러리로 통신하기

라이브러리 세팅

// 터미널 명령어 flutter pub add dio // dio flutter pub add logger // test용 로거 flutter pub add flutter_riverpod // riverpod

1. Dio 세팅

http_util.dart
import 'package:dio/dio.dart'; final Dio dio = Dio( BaseOptions( // fake api baseUrl: "https://jsonplaceholder.typicode.com", headers: { "Content-Type": "application/json" } ) );
  • baseUrl
    • Dio 관련된 메서드 작성 시 url 주소를 적을 때 baseUrl을 생략해도 됩니다.
  • headers
    • 마임 타입 설정

2. Repository

post_repository.dart
// SRP : 데이터를 가져오는 곳 class PostRepository { const PostRepository(); Future<Post> getPost() async { // Future<Response<T>> 반환 Response response = await dio.get("/posts/1"); // dio 설정 상 Map으로 준다. Map<String, dynamic> mapData = response.data; // logger 라이브러리 사용. d는 debug Logger().d(mapData); // Map에서 Post로 return Post.fromMap(mapData); } }
  • getPost() → 비동기 함수로 작성
  • await dio.get("/posts/1")
    • “baseUrl + /posts/1” 주소로 get 요청을 합니다.
    • 반환값은 Map으로 줍니다.
{ "userId": 1, "id": 1, "title": "타이틀" "body": "내용" }
  • Post.fromMap(mapData)
    • post_page_vm.dart에 정의되어 있는 Post class의 메서드입니다.
    • Map<String, dynamic>을 Post 객체로 변환합니다.

3. 리포지토리 테스트

post_repository_test.dart
import 'package:mockapp/post_repository.dart'; void main() async { PostRepository repo = PostRepository(); await repo.getPost(); }
  • 비동기 함수로 작성해야 로그가 제대로 뜹니다.
    • repo.getPost() 로 쓸 경우 getPost()가 비동기 함수이기 때문에 이 부분 코드를 넘어서 계속 진행이 되므로 main이 꺼지기 때문입니다.

4. ViewModel

post_page_vm.dart
class Post { int userId; int id; String title; String body; Post(this.userId, this.id, this.title, this.body); // 이름있는 생성자, Map을 Post로 Post.fromMap(Map<String, dynamic> map) : userId = map["userId"], id = map["id"], title = map["title"], body = map["body"]; } final postProvider = NotifierProvider<PostPageVM, Post?>(() { return PostPageVM(); }); class PostPageVM extends Notifier<Post?> { PostRepository repo = const PostRepository(); @override Post? build() { // 상태 초기화 시작 init(); // 상태 null 초기화 return null; } Future<void> init() async { Post post = await repo.getPost(); state = post; } }
  • Post.fromMap(Map<String, dynamic> map) :
    • 이름이 있는 생성자입니다.
    • Map<String, dynamic>을 받아서 Post 객체로 변환합니다.
  • state
    • 상태를 나타내는 변수 이름입니다.

5. View

post_body.dart
class PostBody extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { Post? model = ref.watch(postProvider); if (model == null) { return Center(child: CircularProgressIndicator()); } else { return Column( children: [ Text("id : ${model.id}"), Text("userId : ${model.userId}"), Text("title : ${model.title}"), Text("body : ${model.body}"), ], ); } } }
  • 통신 중(model == null)일 때는 CircularProgressIndicator 위젯을 그립니다.
  • 통신이 완료되면 Column 위젯을 그립니다.
 
Share article

devleekangho