inblog logo
|
moohyun
    플러터

    Dart에서 통신(실전)

    통신을 통해 데이터를 받아와 출력하는 예제
    화낼거양's avatar
    화낼거양
    Dec 31, 2024
    Dart에서 통신(실전)
    Contents
    http_util.dart 파일 추가ViewViewModelRepository
     
     

    추가된 라이브러리 :

    notion image
    notion image
     
     
     

    http_util.dart 파일 추가

     
    import 'package:dio/dio.dart'; final Dio dio = Dio( BaseOptions( baseUrl: "https://jsonplaceholder.typicode.com", headers: { "Content-Type": "application/json" } ) );
     

    주요 구성 요소

     
    1. Dio 라이브러리 가져오기:
      1. import 'package:dio/dio.dart';
        Dio 라이브러리를 가져와서 HTTP 요청을 처리할 수 있도록 합니다.
    1. Dio 인스턴스 생성:
      1. final Dio dio = Dio( BaseOptions( baseUrl: "https://jsonplaceholder.typicode.com", headers: { "Content-Type": "application/json" } ) );
        • Dio: Dio 클래스의 인스턴스를 생성합니다.
        • BaseOptions: BaseOptions 클래스를 사용하여 기본 설정을 지정합니다.
          • baseUrl: 기본 URL을 설정합니다. 이 예제에서는 "https://jsonplaceholder.typicode.com"을 사용하여 API 요청의 기본 URL을 지정합니다.
          • headers: 요청 헤더를 설정합니다. 여기에는 "Content-Type"이 "application/json"으로 설정되어 있습니다. 이는 요청이 JSON 형식임을 나타냅니다.
     
     

    View

     
    import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:mockapp/post_page_vm.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}"), Row(), ], ); } } }
     

    동작 설명

     
    1. ConsumerWidget: PostBody 클래스는 ConsumerWidget을 상속합니다. 이는 build 메서드에서 WidgetRef 객체를 사용하여 Riverpod 상태 공급자(provider)와 상호작용할 수 있게 합니다.
    1. Post 상태 구독: ref.watch(postProvider) 메서드를 사용하여 postProvider의 현재 상태를 구독합니다. 이 상태는 Post? 타입의 model 변수에 저장됩니다.
    1. 상태 검사:
        • 만약 model이 null이라면, 데이터가 아직 로드되지 않은 상태로 간주하고 CircularProgressIndicator를 렌더링하여 로딩 중임을 표시합니다.
        • 만약 model이 null이 아니라면, 데이터를 성공적으로 로드한 상태로 간주합니다.
    1. 데이터 표시:
        • Column 위젯을 사용하여 Post 객체의 속성(id, userId, title, body)을 표시합니다.
        • Row 위젯이 추가되어 있지만 내용이 없는 상태입니다. 콘텐츠를 추가하거나 제거할 수 있습니다.
     
     
     

    ViewModel

     
    import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:mockapp/post_repository.dart'; class Post { int userId; int id; String title; String body; Post(this.userId, this.id, this.title, this.body); 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; } }
     

    코드 설명

     

    1. Post 클래스 (Model)

    class Post { int userId; int id; String title; String body; Post(this.userId, this.id, this.title, this.body); Post.fromMap(Map<String, dynamic> map) : userId = map["userId"], id = map["id"], title = map["title"], body = map["body"]; }
    • Post 클래스: 게시물 데이터를 나타냅니다.
    • fromMap(Map<String, dynamic> map): Map 객체를 받아서 Post 객체를 초기화합니다.
     

    2. NotifierProvider (State Management)

    final postProvider = NotifierProvider<PostPageVM, Post?>(() { return PostPageVM(); });
    • postProvider: NotifierProvider를 사용하여 PostPageVM의 인스턴스를 제공합니다.
     

    3. PostPageVM 클래스 (ViewModel)

    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; } }
    • PostPageVM: Notifier를 상속받아 상태 관리 및 데이터 로드를 처리합니다.
    • repo: PostRepository 인스턴스로, 데이터를 가져오는 역할을 합니다.
    • build() 메서드: 초기 상태를 설정하고 init 메서드를 호출합니다.
    • init() 메서드: 비동기적으로 데이터를 가져오고, 가져온 데이터를 상태(state)에 저장합니다.
     
     
     

    Repository

     
    // SRP : 데이터를 가져오는 곳 (휴대폰 디바이스(파일), 휴대폰 DB, Firebase(외부서버), 내서버, 공공데이터서버) import 'package:dio/dio.dart'; import 'package:mockapp/http_util.dart'; import 'post_page_vm.dart'; class PostRepository { const PostRepository(); Future<Post> getPost() async{ Response response = await dio.get("/posts/1"); // json 타입은 dio의 경우 Map 타입으로 받아준다. Map<String, dynamic> body = response.data; return Post.fromMap(body); } }
     
    • Dio 라이브러리 가져오기: Dio를 사용하여 API 요청을 보냅니다.
      • import 'package:dio/dio.dart'; import 'package:mockapp/http_util.dart'; import 'post_page_vm.dart';
         
    • PostRepository 클래스 정의:
      • class PostRepository { const PostRepository(); }
        PostRepository 클래스를 정의하고, 데이터를 가져오는 기본 역할을 담당합니다. 생성자는 상수 생성자이므로 불변 객체로 만들 수 있습니다.
         
    • getPost() 메서드:
      • Future<Post> getPost() async { Response response = await dio.get("/posts/1"); Map<String, dynamic> body = response.data; return Post.fromMap(body); }
      • Response: 비동기적으로 HTTP GET 요청을 보내고 응답을 받습니다. 이 예시에서는 "/posts/1" endpoint에서 데이터를 가져옵니다.
      • Map<String, dynamic> body: Dio의 응답 데이터를 Map<String, dynamic> 타입으로 변환합니다.
      • Post.fromMap(body): 변환된 Map 객체를 사용하여 Post 객체를 생성하고 반환합니다.
     
     
     
     
     
    아래의 라이브러리는 log를 보기 좋게 사용하기 위한 라이브러리 입니다. (필수 다운 필요 X)
    notion image
     
    notion image
    Share article
    Contents
    http_util.dart 파일 추가ViewViewModelRepository

    moohyun

    RSS·Powered by Inblog