[Flutter] KeepAlive 세팅하기

겨레·2024년 7월 25일

[Flutter] Riverpod v2

목록 보기
3/7
post-thumbnail

지난 시간에 했던 제너레이션된 코드를 분석해 보는 타임~~~



그 전에 String뿐 아니라 async로도 값을 반환할 수 있다는 것도 확인해보자!



  • code_generation_provider.dart 코드
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'code_generation_provider.g.dart';

// code_generation이 riverpod에 추가가 된 이유

// (1) 어떤 Provider를 사용할지 결정할 고민 할 필요가 없도록!
// Provider, FutureProvider, StreamProvider
// - 어떤 종류의 Provider를 쓸지 고민하지 않아도 code_generation을 쓰면 riverpod에서 알아서 결정해줌.
// - StateNotifierProvider는 명시적으로 code_generation 할 수 있음.

// (1)-1. Provider 생성
final _testProvider = Provider<String>((ref) => 'Hello Code Generation');

// (1)-2. riverpod 어노테이션 작성하고 일반 함수로 작성
// (1)-3. <String>을 반환받고 싶으니까 String으로 작성해주고
// (1)-4. ref를 받아준다 => 어떻게? => 현재 함수 이름(첫글자는 대문자로) + Ref  변수명
// (1)-5. { } 함수 안에 return 반환해주기
// (1)-6. 터미널에 flutter pub run build_runner build

String gState(GStateRef ref) {
  return 'Hello Code Generation';
}

// Future값 넣어보기!
// flutter pub run build_runner build 까지 해주기

Future<int> gStateFuture(GStateFutureRef ref) async {
  await Future.delayed(const Duration(seconds: 3));

  return 10;
}

CodeGenerationScreen으로 가서 받아주기

저장하고 실행해보면...

Loading 됐다가 3초 후에 아래와 같이 잘 나오는 걸 볼 수 있다.

이렇게 나오는 이유는...?

FutureProviderScreen로 가서 보면 FutureProvider를 쓸 때,
state.when을 써서 반환해줘야 된다고 해둠.

  • code_generation_screen.dart 코드
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_study/layout/defalut_layout.dart';
import 'package:riverpod_study/riverpod/code_generation_provider.dart';

class CodeGenerationScreen extends ConsumerWidget {
  const CodeGenerationScreen({super.key});

  
  Widget build(BuildContext context, WidgetRef ref) {
    final state1 = ref.watch(gStateProvider);
    final state2 = ref.watch(gStateFutureProvider);

    return DefalutLayout(
      title: 'CodeGenerationScreen',
      body: Column(
      crossAxisAlignment: CrossAxisAlignment.stretch
        children: [
          Text('State1 : $state1'),
          state2.when(
          	// 'State2 : $data'
            data: (data) {
              return Text(
                data.toString(),
                textAlign: TextAlign.center,
              );
            },
            error: (err, stack) => Text(
              err.toString(),
            ),
            loading: () => const Center(
              child: CircularProgressIndicator(),
            ),
          ),
        ],
      ),
    );
  }
}

저장하고 앱 재실행 후, CodeGenerationScreen 버튼 눌러서 다시 들어가보면...

로딩이 3초간 떴다가 10이라는 숫자가 나온다.

드래그 된 부분은 아래와 같이 바꿔준다.

그러면 State2 : 10 이라고 나오는 걸 볼 수 있다.

이를 통해서 FutureProvider도 쓸 수 있다는 걸 증명해냄!!!



그럼 원래 해보려고 했던 제너레이션된 코드 분석을 본격적으로 해보자~~~

code_generation_provider.g.dart 파일을 봐보자.
원래는 Provider라는 키워드만 사용해서 생성을 했었음.
그런데 AutoDisposeProvider라고 적혀있음...

AutoDispose 이거 auto_dispose_modifier 할 때 배웠었음!
autoDispose를 어떤 프로바이더든 등록해주면 사용되지 않는 순간에는 삭제가 됐음.

일반적으로 @riverpod 으로 code_generation 하면
AutoDispose 키워드가 자동으로 붙음.

그럼 AutoDispose를 쓰지 않고 그냥 일반 Provider를 생성하고 싶을 땐???

code_generation_provider.g.dart 보면 다른 건 다 AutoDisposeFutureProvider인데,
이것만 FutureProvider로 만들어진 걸 볼 수 있다.



  • code_generation_provider.dart 코드
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

part 'code_generation_provider.g.dart';

// code_generation이 riverpod에 추가가 된 이유

// (1) 어떤 Provider를 사용할지 결정할 고민 할 필요가 없도록!
// Provider, FutureProvider, StreamProvider
// - 어떤 종류의 Provider를 쓸지 고민하지 않아도 code_generation을 쓰면 riverpod에서 알아서 결정해줌.
// - StateNotifierProvider는 명시적으로 code_generation 할 수 있음.

// (1)-1. Provider 생성
final _testProvider = Provider<String>((ref) => 'Hello Code Generation');

// (1)-2. riverpod 어노테이션 작성하고 일반 함수로 작성
// (1)-3. <String>을 반환받고 싶으니까 String으로 작성해주고
// (1)-4. ref를 받아준다 => 어떻게? => 현재 함수 이름(첫글자는 대문자로) + Ref  변수명
// (1)-5. { } 함수 안에 return 반환해주기
// (1)-6. 터미널에 flutter pub run build_runner build

String gState(GStateRef ref) {
  return 'Hello Code Generation';
}

// Future값 넣어보기!
// flutter pub run build_runner build 까지 해주기

Future<int> gStateFuture(GStateFutureRef ref) async {
  await Future.delayed(const Duration(seconds: 3));

  return 10;
}

// AutoDispose를 쓰지 않고 일반 Provider를 생성하기
// 이땐 대문자 + () =>  @Riverpod()
// 그리고 이 대문자 Riverpod 어노테이션은 ()여기에 파라미터를 하나 받음!
// 그 파라미터는 => keepAlive (살려둬라)
// keepAlive의 기본값은 false
// AutoDispose가 안 붙는 Provider(일반 Provider)를 만들고싶을 땐 true
(
  keepAlive: true,
)
Future<int> gStateFuture2(GStateFuture2Ref ref) async {
  await Future.delayed(const Duration(seconds: 3));

  return 10;
}

// (2) Parameter => 리버팟에서는 Family
// Family 파라미터를 일반 함수처럼 사용할 수 있도록!

  • code_generation_screen.dart 코드
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_study/layout/defalut_layout.dart';
import 'package:riverpod_study/riverpod/code_generation_provider.dart';

class CodeGenerationScreen extends ConsumerWidget {
  const CodeGenerationScreen({super.key});

  
  Widget build(BuildContext context, WidgetRef ref) {
    final state1 = ref.watch(gStateProvider);
    final state2 = ref.watch(gStateFutureProvider);
    final state3 = ref.watch(gStateFuture2Provider);

    return DefalutLayout(
      title: 'CodeGenerationScreen',
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Text('State1 : $state1'),
          state2.when(
            data: (data) {
              return Text(
                'State2 : $data',
                textAlign: TextAlign.center,
              );
            },
            error: (err, stack) => Text(
              err.toString(),
            ),
            loading: () => const Center(
              child: CircularProgressIndicator(),
            ),
          ),
          state3.when(
            data: (data) {
              return Text(
                'State3 : $data',
                textAlign: TextAlign.center,
              );
            },
            error: (err, stack) => Text(
              err.toString(),
            ),
            loading: () => const Center(
              child: CircularProgressIndicator(),
            ),
          ),
        ],
      ),
    );
  }
}

앱을 재실행하고, CodeGenerationScreen 버튼을 눌렀을 때

state1은 그대로 바로 나오고
state2, state3은 로딩이 되고 값이 나온다.

다시 뒤로 갔다가 들어가면...

state2만 렌더링 됐다가 뜨고,
state3은 다시 렌더링되지 않고 바로 뜨는 걸 볼 수 있다.

왜냐면... keepAlive: true 해뒀기 때문!

profile
호떡 신문지에서 개발자로 환생

0개의 댓글