개발/Flutter

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

T'Challa 2021. 6. 20. 21:43

Controller

룰? 특징?

  • .obs 변수를 생성하여 조작하는 코드 작성
  • Repository의 데이터를 consume (Provider의 데이터를 호출)
  • 모든 controller에는 하나의 repository만 가진다.(GetX widget에서 controller를 초기화 하는데 필요함)
  • 만약 하나의 페이지에서 두 개의 repository가 필요한 경우 두 개의 GetX widget(Controller) 을 사용
  • 여러 페이지에서 동일한 controller를 사용하는 경우는 아래 하나 뿐이다.
    • 모든 페이지의 데이터가 단일 repository를 사용하는 경우 ( 뭐 login user? 이런 것..?)

위의 이유는 GetX를 사용하고 GetX의 모든 기능을 사용하기 위함이다.

왜냐하면 controller는 GetX 위젯과 쓰여야 하는데,

만약 이 controller가 두 개의 repository로부터 값을 받고 있다고 가정해보자

한 개의 엔티티가 수정됐을 때, controller는 위젯을 업데이트 해야 한다.

그러면 다른 한 개의 엔티티를 사용하지 않는 위젯까지 업데이트 해야 한다.

그렇기 때문에 각 widget 마다 하나의 controller를 사용하는 것이 좋다.

각 widget은 그것들의 .obs변수가 변경됐을 때만 다시 렌더링될 것이다.

 

실습코드

import 'package:get/get.dart';
import 'package:getx_practice/app/data/model/model.dart';
import 'package:getx_practice/app/data/repository/posts_repository.dart';
import 'package:meta/meta.dart';

class MyController extends GetxController {
  //repository required
  final MyRepository repository;
  MyController({required this.repository}) ;

  //use o snippet getfinal para criar está variável  
  final _postsList = <MyModel>[].obs;
  get postList => this._postsList.value;
  set postList(value) => this._postsList.value = value;
  ///função para recuperar todos os posts
  getAll(){
    repository.getAll().then( (data){ this.postList = data; } );
  }
}

repository에 required 를 사용한 이유는 repository를 통해 데이터를 검색할 것이기 때문이다.

postsList는 .obs 이다. 

private (변수명 앞에 _) 이므로 getter setter 생성

상태 변경에 대한 책임은 controller에 두는 것이 좋다.

다른 곳에서 .value 를 사용할 필요없이 setter를 통해 controller 내부에서 상태 변경

getAll 함수를 클래스에 관계없이(Provider, Repository) 동일한 이름으로 사용하여

추후 검색에 용이하게 만듦

Future 대신에 .then 을 사용

 

.then

함수의 return 을 기다리고 date를 할당하므로 FutureBuilder를 사용할 필요가 없다.

 

위 controller 구체화

import 'package:get/get.dart';
import 'package:getx_practice/app/data/model/model.dart';
import 'package:getx_practice/app/data/repository/posts_repository.dart';

class DetailsController extends GetxController {
  final MyRepository repository;
  DetailsController({required this.repository});

  final _post = MyModel().obs;
  get post => this._post.value;
  set post(value) => this._post.value = value;

  edit(post) {
    print('edit');
  }

  delete(id) {
    print('delete');
  }
}