본문 바로가기
Flutter/Package

플러터에서 Rxdart 패키지 사용 방법과 옵션

by Maccrey Coding 2024. 8. 1.
반응형

플러터(Flutter) 개발에서 반응형 프로그래밍을 구현할 때, rxdart 패키지는 매우 유용한 도구입니다.

이 글에서는 rxdart 패키지를 사용하는 방법과 주요 옵션에 대해 설명합니다.

 

 

rxdart | Dart package

RxDart is an implementation of the popular ReactiveX api for asynchronous programming, leveraging the native Dart Streams api.

pub.dev

 

 

1. Rxdart 패키지란?

rxdart는 Dart 언어용 반응형 확장을 제공하는 패키지입니다.

이는 RxJava나 RxJS와 비슷한 기능을 제공하며, 스트림(Stream)과 옵저버블(Observable) 개념을 이용해 비동기 작업을 보다 쉽게 관리할 수 있게 해줍니다.

 

2. Rxdart 패키지 설치

우선, rxdart 패키지를 프로젝트에 추가해야 합니다. pubspec.yaml 파일에 다음을 추가하세요

dependencies:
  flutter:
    sdk: flutter
  rxdart: ^0.27.1

그런 다음, 터미널에서 다음 명령어를 실행하여 패키지를 설치합니다

flutter pub get

3. 기본 사용법

rxdart의 기본 개념은 스트림과 옵저버블입니다. 여기서는 BehaviorSubject를 예로 들어 설명합니다.

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  // BehaviorSubject는 최신 상태를 보유하고, 새 구독자가 해당 상태를 즉시 받을 수 있게 합니다.
  final BehaviorSubject<int> _counter = BehaviorSubject<int>.seeded(0);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('RxDart Example'),
      ),
      body: Center(
        child: StreamBuilder<int>(
          stream: _counter.stream,
          builder: (context, snapshot) {
            return Text('Counter: ${snapshot.data}');
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // 최신 값을 얻고, 1을 더한 후 추가합니다.
          _counter.add(_counter.value + 1);
        },
        child: Icon(Icons.add),
      ),
    );
  }

  @override
  void dispose() {
    // 사용이 끝나면 BehaviorSubject를 닫습니다.
    _counter.close();
    super.dispose();
  }
}

위 예제에서는 BehaviorSubject를 사용하여 카운터 상태를 관리하고, 이를 StreamBuilder를 통해 UI에 반영합니다.

4. 주요 옵션 및 연산자

rxdart는 다양한 연산자를 제공하여 스트림을 조작할 수 있습니다. 몇 가지 주요 옵션과 연산자를 살펴보겠습니다.

4.1. map

map 연산자는 스트림의 각 요소에 함수를 적용하여 새로운 스트림을 만듭니다.

final observable = Stream.fromIterable([1, 2, 3]).map((value) => value * 2);
observable.listen(print); // 2, 4, 6 출력

4.2. filter (where)

where 연산자는 스트림의 요소를 필터링하여 조건에 맞는 요소만 통과시킵니다.

final observable = Stream.fromIterable([1, 2, 3, 4, 5]).where((value) => value % 2 == 0);
observable.listen(print); // 2, 4 출력

4.3. combineLatest

combineLatest는 여러 스트림의 마지막 값을 결합하여 새로운 스트림을 만듭니다.

final observable1 = Stream.fromIterable([1, 2, 3]);
final observable2 = Stream.fromIterable([4, 5, 6]);
final combined = Rx.combineLatest2(observable1, observable2, (a, b) => a + b);
combined.listen(print); // 5, 6, 7 출력

4.4. debounce

debounce 연산자는 지정된 시간 동안 스트림의 요소 방출을 지연시킵니다.

final observable = Stream.fromIterable([1, 2, 3]).debounceTime(Duration(seconds: 1));
observable.listen(print); // 3만 출력 (debounce 때문에 앞의 요소들이 무시됨)

5. 실전 예제

rxdart를 이용하여 간단한 검색 기능을 구현해보겠습니다.

사용자가 입력하는 검색어를 받아 디바운스 처리하고, 서버에 요청을 보내 검색 결과를 표시하는 예제입니다.

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SearchPage(),
    );
  }
}

class SearchPage extends StatefulWidget {
  @override
  _SearchPageState createState() => _SearchPageState();
}

class _SearchPageState extends State<SearchPage> {
  final TextEditingController _controller = TextEditingController();
  final BehaviorSubject<String> _searchSubject = BehaviorSubject<String>();
  final List<String> _results = [];

  @override
  void initState() {
    super.initState();

    _searchSubject.stream
        .debounceTime(Duration(milliseconds: 500))
        .distinct()
        .switchMap((query) => _search(query))
        .listen((results) {
      setState(() {
        _results.clear();
        _results.addAll(results);
      });
    });
  }

  Stream<List<String>> _search(String query) async* {
    // 여기서는 간단히 검색 결과를 시뮬레이션합니다.
    await Future.delayed(Duration(seconds: 1)); // 네트워크 지연 시간 시뮬레이션
    yield List.generate(5, (index) => '$query 결과 $index');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('RxDart Search Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Column(
          children: [
            TextField(
              controller: _controller,
              onChanged: (query) => _searchSubject.add(query),
              decoration: InputDecoration(
                hintText: '검색어를 입력하세요...',
              ),
            ),
            Expanded(
              child: ListView.builder(
                itemCount: _results.length,
                itemBuilder: (context, index) {
                  return ListTile(
                    title: Text(_results[index]),
                  );
                },
              ),
            ),
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    _searchSubject.close();
    super.dispose();
  }
}

이 예제에서는 사용자가 텍스트 필드에 입력하는 검색어를 받아 _searchSubject에 추가하고, debounceTime과 distinct 연산자를 사용하여 불필요한 네트워크 요청을 줄입니다.

그런 다음, switchMap을 사용하여 검색 결과 스트림을 처리하고 UI에 표시합니다.

마무리

rxdart 패키지를 사용하면 플러터 애플리케이션에서 반응형 프로그래밍을 쉽게 구현할 수 있습니다.

이 글에서는 rxdart의 기본 사용법과 주요 연산자에 대해 설명했습니다.

더 깊이 있는 내용을 알고 싶다면 rxdart 공식 문서와 추가 자료를 참고하세요.

 

Starting Google Play App Distribution! "Tester Share" for Recruiting 20 Testers for a Closed Test.

 

Tester Share [테스터쉐어] - Google Play 앱

Tester Share로 Google Play 앱 등록을 단순화하세요.

play.google.com

 

반응형