개발/Flutter

Flutter GetX 패턴으로 프로젝트 구성해보기(3) - Data

T'Challa 2021. 6. 17. 00:22

차근차근 getx_pattern 사이트에 나와있는대로 프로젝트 구조를 설정해보도록 하겠다.

먼저 lib 폴더 아래 app 폴더를 생성한다.

getx_pattern에서 제안하는 모든 것들은 app 폴더 하위에 생성될 것이다.

Data

data폴더를 app 폴더 하위에 생성한다. data 폴더는 정말 데이터 조작에 사용하는 model, repository, provider 들이 들어갈 폴더일 뿐이다.

 

Provider

http 요청 또는 데이터베이스 조작을 수행한다.

데이터 하위에 provider 폴더를 생성하고 예제를 살펴보기 위해 api.dart 를 생성했다.

import 'dart:convert';
import 'package:getx_practice/app/data/model/model.dart';
import 'package:http/http.dart' as http;

// our base url
const baseUrl = 'https://jsonplaceholder.typicode.com/posts/';

//our class responsible for encapsulating http methods
class MyApiClient {
//your http client can be http, http.Client, dio, just bring your methods here and they will work normally :D
  final http.Client httpClient;
  MyApiClient({required this.httpClient});

  //a quick example, here we are retrieving all posts made available by api(100)
  getAll() async {
    try {
      var response = await httpClient.get(baseUrl);
      if (response.statusCode == 200) {
        Iterable jsonResponse = json.decode(response.body);
        List<MyModel> listMyModel =
            jsonResponse.map((model) => MyModel.fromJson(model)).toList();
        return listMyModel;
      } else
        print('error');
    } catch (_) {}
  }
}

위 코드를 사용하는데, 일단 아직 이해가 안가는 부분은 있지만 jsonplaceholder에 요청하여 데이터를 가져오는 것 같다.

그리고 json 데이터를 파싱까지 해서 return 을 해준다.

추후 프로젝트 시, 백엔드와 이어주는 부분을 담당할 것이다.

 

Model

Model 클래스에는 객체를 json으로 json을 객체로 변환하는 역할을 하는 toJson, fromJson이라는 attribute와 두 가지 메서드가 있다.

폴더 구조는 위와 같이 data 하위에 model 폴더를 생성한다.

class  MyModel {
  
  int id = 0;
  String title = '';
  String body = '';

  MyModel ({ id, title, body});

  MyModel . fromJson ( Map < String , dynamic > json){
      this .id = json[ 'id' ];
      this .title = json[ 'title' ];
      this .body = json[ 'body' ];
  }

  Map < String , dynamic >  toJson (){
    final  Map < String , dynamic > data =  new  Map < String , dynamic > ();
    data[ 'name' ] =  this .title;
    data[ 'body' ] =  this .body;
    return data;
  }
}

 

 

백엔드랑 통신할 때, 대부분 json 을 사용하다보니 위와 같이 기본적으로 메소드를 생성해놓으면 편할 것 같긴 하다. 좋은 아이디어인 것 같다. (아직 잘 몰라 이렇게 생각할 수 있다.... 경험이 없어서....)

 

Repository

Entity를 분리하는 역할을 한다. Entity는 Provider에서 사용할 데이터베이스의 모든 테이블이다.

Repository의 목표는 컨트롤러에서 데이터 소스를 추상화하고 분리하는 것을 목표로 한다.

언젠가 프로젝트의 API나 데이터베이스를 변경하는 경우 Provider 파일만 변경하고 Repository를 변경할 필요가 없다.

Provider 함수를 호출하는 역할만 담당하므로 로직이 없다. 

컨트롤러에서 데이터의 출처를 알 필요없이 데이터 사용할 수 있도록 한다. 

provider 와 controller 사이에서 중간 역할을 담당한다.

 

위와 같이 data 하위에 repository 폴더를 생성한다.

import 'package:getx_practice/app/data/provider/api.dart';
import 'package:meta/meta.dart';

//Repository responsible for the post entity !!
// remembering that each entity that somehow persists with the database, be it an api or sqlite
//must have an exclusive repository
class MyRepository {
  final MyApiClient apiClient;

  MyRepository({required this.apiClient});

  getAll() {
    return apiClient.getAll();
  }
}

Provider에서 api 호출한 결과를 받아 return 하고 있다.

 

일단 data 까지는 코드를 보니 머리속에 좀 정리가 되는 것 같다..

다음에는 controller 부터 더 이해를 해보자