Vintage appMaker의 Tech Blog

[Flutter] setState 없이 화면변경 - ValueListenableBuilder 본문

Source code or Tip/Flutter & Dart

[Flutter] setState 없이 화면변경 - ValueListenableBuilder

VintageappMaker 2022. 6. 27. 10:26

 

 

 


Flutter에서 화면갱신을 위해서
setState를 남발하다보면
차일드까지 모두 갱신하므로
엄청나게 느려지게 된다

 


 

Flutter에서 setState() 함수를 사용하지 않고 바인딩 된 변수값을 직접 액세스하여 변경된 값으로 Widget을 갱신하려고 한다면

ValueListenableBuilder

위젯으로 wrap을 하면 가능하다. 여기서 중요한 네임드 파라메터는

  • valueListenable : 모니터링할 변수
  • builder : 값 변경시 화면을 구성할 builder 함수
    • 첫번째 파라메터 : Context
    • 두번째 파라메터 : valueListenable에 정의된 변수
    • 세번째 파라메터 : Widget

이다. 그리고 builder의 경우, 특정조건에서는 넘겨지는 파라메터의 데이터 형을 선언해야 한다.그러나 대부분 데이터 형을 선언하지 않고 쓰고 있다. 

ValueListenableBuilder(
  valueListenable: _param,
  builder: (ctx, int value, child) {
    return Container(
      color: Colors.redAccent,
      child: Center(
        child: Text("${value}", style: TextStyle(fontSize: 30, color: _getColor(value))),
      ),
    );
  },
)

 

그리고 valueListenable 에 정의된 변수는 state 클래스에서 정의했다.

valueListenable 로 정의된 변수의 값을 액세스 하려면 [변수명.value] 형식으로 사용해야 한다. 

ValueNotifier<int> _param = ValueNotifier<int>(0);

[전체소스]

import 'dart:io';
import 'package:flutter/material.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ValueListenableBuilder Demo',
      theme: ThemeData(
        primarySwatch: Colors.yellow,
      ),
      home: const MyHomePage(title: 'ValueListenableBuilder Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}


class _MyHomePageState extends State<MyHomePage> {
  var color_table  = <Color>[
    Colors.black,
    Colors.red, 
    Colors.yellow, 
    Colors.white,  
  ];

  Color _getColor(int n) => color_table[n % (color_table.length)];

  ValueNotifier<int> _param = ValueNotifier<int>(0);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: ValueListenableBuilder(
        valueListenable: _param,
        builder: (ctx, int value, child) {
          return Container(
            color: Colors.redAccent,
            child: Center(
              child: Text("${value}", style: TextStyle(fontSize: 30, color: _getColor(value))),
            ),
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          _param.value++;
        },
        child: const Icon(Icons.add),
      ),
    );
  }
}
Comments