[Flutter] 230119 - 영상통화 앱 만들기

tissue·2023년 1월 19일

Flutter

목록 보기
7/8
post-thumbnail

수강 강의: https://url.kr/inflearn
진도: 104강 / 178강

① [이론] FutureBuilder

1. 반환하는 Future값이 없는 경우 State

Data: NULL
Connection State: None

2. 반환하는 Future값이 있는 경우 State

1) 값을 받아오는 동안

Data: NULL
Connection Sate: Connection State.waiting

2) 값이 받아졌을 때

Data: (값)
Connection State: Connection State.done

3. State 캐싱

Connection State가 바뀔 때 마다 빌더 함수가 새로 불리기 떄문에 SetState를 실행하지 않아도 화면이 바뀌는 것을 알 수 있다.

그럼 Connection State가 Done이 된 상태로 SetState함수를 실행하면 어떻게 될까?

SetState를 하면 Build가 다시 불리기 때문에 당연히, Future Builder가 다시 실행된다.
Future Builder가 다시 실행되는 동안, Connection State는 waiting이 되고, Data는 null이 되지 않고 그전 데이터가 그대로 유지된다.
그리고나서 Connection State가 Done이 되면 Data에 새로운 Future값이 들어온다.

이를 캐싱이라고 한다.
캐싱 : FutureBuilder가 기존의 데이터 값을 기억하는 것을 말함

이를 어디에 사용할 수 있을까?

Facebook같은 앱에서, 새로운 항목을 로딩 할 때 화면 전체가 로딩되지 않고 일부에만 로딩화면이 보이고 로딩이 완료된다. 이것은 기존 데이터를 유지하는 캐싱을 이용한 것이다.

if(snapshot.connectionState == ConnectionState.waiting) CicularProgressIndicator

와 같이 if문을 사용해서 로딩해야 하는 항목에만 적용해주는 것이 더 효율적이다. 이렇게 하지 않고 앱 전체가 로딩되게 하면 앱이 굉장히 느려보이기도 한다.

4. Error

에러는 throw로 받아오면 된다.

throw Exception('에러가 발생했습니다.')

로 작성할 경우, Error: Excetion: 에러가 발생했습니다. 로 화면에 잘 나온다.

Error도 캐싱이 될까?

throw를 주석처리하고 다시 SetState 하면 waiting이 되는 동안 Error는 그대로이다. SetState가 Done이 되어야 Error:None으로 나온다. 따라서 Error도 캐싱이 된다.

5. hasData

snapshot.hasData : snapshot 값이 있으면 Ture, 없으면 False를 반환한다

② [이론] StreamBuilder

Stream<int> streamNumbers() async* {
	for (int i = 0; i < 10; i ++){
    	await Future.delayed(Duration(seconds: 1))
        yield i;
    }

위와 같은 코드로 Stream을 만들어줬다.
Data가 ConnectionState.active 에서 시작해서, 1초마다 0~9까지 올라가는 코드이다.
9까지 올라가면 ConnectionState.done 상태가 된다.

StreamBuilder도 FutureBuilder와 마찬가지로 캐싱이 된다.
StreamBuilder의 경우에는 모든 Build를 닫는 것까지 작업을 해주기 때문에 우리가 신경 쓸 필요가 없다는 장점이 있다.

③ 영상통화 앱

  • Agora API
  • RTC (Reacl Time Communication)
  • Shadow (UI)
  • Stack

0. 프로젝트 세팅

  1. Agora API
    https://pub.dev/packages/agora_rtc_engine

  2. Permission Handler
    https://pub.dev/packages/permission_handler

1. 화면 구현

1. Expanded로 차지한 영역 중에서 최소한의 값만 차지하게 하기

mainAxisSize: MainAxisSize.min
사이즈를 최소한의 값만 차지하도록 하려면 MainAxisSize.min을 사용하면 된다.
여기서 조금 더 키우고 싶으면 padding값을 이용해서 키울 수 있다.

2. Expanded로 차지한 영역 중에서 가장 아래에 위치하게 하기

Column으로 감싸주고 mainAxisAlignment: MainAxisAlignment.end 로 설정해주면 가장 아래로 위치하게 된다.

3. Text 자간 설정하기

letterSpacing : (값) 값이 커질수록 자간이 커진다

4. Container 테두리 둥글게 하기

borderRadius: BorderRadius.circular(값)
테두리 둥글게 값이 커질수록 둥굴어짐

5. Container 박스 그림자 넣기

BoxSadow

BoxShadow: (
	color: Colors.blue[300]!,
    blurRadius: 12.0 // 퍼지는 영역
    spreadRadius: 2.0, // 그림자 영역
    )

6. 원하는 위치에 정렬

Align( alignment: Alignment.topLeft, child: Text('Hi'))

Align 함수를 이용해서 원하는 위치에 정렬 할 수 있다.

2. AGORA API 연동 (화상채팅)

1. 권한 받아오기

Future<bool> init() async {
	final resp = await [Permission.camera, Permission.microphone].requewst(); // 권한을 받아온다
    
    final cameraPermission = resp[Permission.camera]; // 카메라 권한 값을 cameraPermission에 저장
    final microphonePermission = resp[Permission.microphone]; // 마이크 권한 값을 microphonePermission에 저장
    
    if(cameraPermission != PermissionStatus.granted || microphonePermission != PermissionStatus.granted){
    	throw '카메라 또는 마이크 권한이 없습니다.';
    }
    
    return true;
}

PermissionStatus.granted 는 권한이 있는 것을 뜻한다.
따라서, if문은 '@에 대한권한이 없다면~' 을 말한다.

2. 이벤트 핸들러

이벤트 핸들러로 4가지 경우를 제어할 수 있다.

1) 채널에 본인이 입장한 경우

나의 uid 저장

2) 내가 채널에서 나갔을 때

나의 uid null

3) 상대가 채널에 입장했을 때

상대의 uid 저장

4) 상대가 채널에서 나갔을 때

상대의 uid null

=> API만 사용하면 돼서 생각보다는 쉬웠다

3. 실제 서비스?

실제로 이 서비스를 출시했을 때, 어떤 식으로 서비스를 구현하게 될까?

가장 문제는 토큰이 24시간만 유용하다는 것이다.
따라서 서버를 만들어야 한다.
서버와 아고라 API를 연결해야한다.

그렇게 해서 A와 B라는 사람이 영상통화를 할 때 토큰을 받아올 수 있어야 한다.

④ [이론] Buy vs Build

구매할 것인가 직접 만들것인가?

어떤 걸 만들고 어떤 API를 구매해서 써야 할까?

좋은 이야기인 것 같아서 캡쳐해왔다


지금 봤을 때는 Buy로 초기 개발을 하고 나중에 Build로 하는게 좋을 것 같은데.. 이미 Buy한 걸로 만든 서비스를 Build한 걸로 대체하는게 쉽지 않을 것 같긴 함

⑤ 일정 스케쥴러

0. 미리보기

1. 화면 구현

1. 캘린더 커스텀

defaultDecoration, weekendDecoration, selectedDecoration 모두 따로 지정해주어야 한다.
따라서 BoxDecoration을 따로 위젯으로 만든 뒤에 넣어주는 것이 좋다.
TextStyle도 마찬가지로 defaultTextStyle, weekendTextStyle, selectedTextStyle 모두 따로 지정해주어야 하므로 TextStyle 위젯을 따로 만든 뒤에 넣어주는 것이 좋다.

2. 에러 잡기

1월에 Focus가 된 상태로 2월 날짜를 누르면 에러가 난다.
첫 번째는 눌렀을 때 빨간색 에러 화면이 보이는 것이고, 두 번째는 날짜 Focus가 이동되지 않는 것이다.

1) 눌렀을 때 빨간색 에러 화면이 보이는 것

defaulDecoration은 BorderRadius를 주었는데, outsideDecoration은 Circle 형태로 BorderRadius가 불가능해서 에러가 난다. 따라서 outsideDecoration도 따로 설정해준다.
outsideDecoration: defaultBoxDeco

2) 날짜 Focus가 이동되지 않는 것

1월 => 2월로 날짜를 선택했을 때 focuseDay도 같이 이동하도록 해주면 된다.

setState(() {
            this.selectedDay = selectedDay;
            this.focuseDay = selectedDay;
          },

3. 언어 변경

Intl 패키지를 이용해서 언어를 변경한다.

현재까지 강의를 들으며 진행한 사항은 아래와 같다.

profile
Better than Yesterday!

0개의 댓글