Never give up

Flutter - Provider listen : false with http 본문

Flutter

Flutter - Provider listen : false with http

대기만성 개발자 2020. 8. 3. 16:31
반응형

Provider를 사용하다보면 어떤곳에는 false를 사용하고, 다른곳에서는 사용하지 않는데

이 차이를 알아보겠습니다

결론부터 말하자면 notifyListeners()를 호출해서 바로 UI에서 변경되는 부분은 true
(default가 true이기 때문에 따로 설정해줄 필요는 없습니다)

그리고 데이터만 변경하고 UI를 변경하지 않는곳에서는 listen : false를해야됩니다

예제 코드로 알아보겠습니다

 

Splash Screen

class SplashScreen extends StatefulWidget {
  @override
  _SplashScreenState createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> {
  @override
  void initState() {
    super.initState();
    _init();
  }

  void _init() async {
    await Provider.of<ListItem>(context, listen: false).setItems();

    Navigator.push(
        context, MaterialPageRoute(builder: (context) => MainScreen()));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.blue,
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            CircularProgressIndicator(
                backgroundColor: Colors.white, strokeWidth: 6),
            SizedBox(height: 20),
            Text('Now loading...',
                style: TextStyle(
                    fontSize: 40,
                    fontWeight: FontWeight.w700,
                    color: Colors.white,
                    shadows: <Shadow>[
                      Shadow(offset: Offset(4, 4), color: Colors.white10)
                    ],
                    decorationStyle: TextDecorationStyle.solid))
          ],
        ),
      ),
    );
  }
}

 


NetworkHelper

NetworkHelper
class NetworkHelper {
  String url = 'https://jsonplaceholder.typicode.com/todos';

  Future getData() async {
    http.Response response = await http.get(url);

    if (response.statusCode == 200) {
      var data = jsonDecode(response.body);

      return data;
    } else {
      print(response.statusCode);
    }
  }
}

 

ListItem, ListData

class ListData {
  String title;
  bool completed;

  ListData({this.title, this.completed});

  void toggleStatus() {
    completed = !completed;
  }
}

class ListItem extends ChangeNotifier {
  List<ListData> _items = [];

  UnmodifiableListView<ListData> get getItems {
    return UnmodifiableListView(_items);
  }

  int get getLength {
    return _items.length;
  }

  void addItems(ListData data) {
    _items.add(data);
    notifyListeners();
  }

  Future<void> setItems() async {
    NetworkHelper _helper = NetworkHelper();
    var decodedData = await _helper.getData();

    if (decodedData != null) {
      List<ListData> _data = [];

      for (int i = 0; i < 50; i++) {
        _data.add(ListData(
            title: decodedData[i]['title'],
            completed: decodedData[i]['completed']));
      }

      _items?.clear();
      _items.addAll(_data);
      notifyListeners();
    }
  }

  void changeStatus(ListData data) {
    data.toggleStatus();
    notifyListeners();
  }
}

 

메인화면

class ProviderExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var items = Provider.of<ListItem>(context);
    return Scaffold(
        appBar: AppBar(title: Text('Provider')),
        body: Container(
          padding: EdgeInsets.symmetric(horizontal: 10, vertical: 4),
          child: ListView.builder(
            itemCount: items.getLength,
            itemBuilder: (context, index) {
              return Card(
                child: ListTile(
                  title: Text(items.getItems[index].title),
                  trailing: Checkbox(
                    value: items.getItems[index].completed,
                    onChanged: (value) {
                      items.changeStatus(items.getItems[index]);
                    },
                  ),
                ),
              );
            },
          ),
        ));
  }
}

 

먼저 오래걸리는 작업인 api값을 가져오는것은 Splash Screen에서 처리합니다

(추가 설명이 필요하다면 링크 참조 : https://devmemory.tistory.com/3?category=935233)

 

윗 부분의 과정을 말하면 

1. ListItem 클래스의 setItems 메소드에서 url에 있는 API값을 가져와서 디코딩

2. 디코딩된 값을 List에 추가

3. async await을 통해 작업이 끝날때까지 대기 후 MainScreen으로 이동

그 후 메인화면에서 Provider를 통해 List를 가져와서 Listview에 출력합니다

여기서 포인트는 Splash Screen에서는 UI에서 데이터를 변경이 일어나지 않으니

Provider<ListItem>(context, listen : false)가 있고

메인화면에서는 변경이 일어나니 listen : false부분이 없습니다

fakeAPI 출처 : jsonplaceholder.typicode.com/

반응형
Comments