크롬이 한번 튕겨서 저장이 안되고 다 날라감... ㅅㅂ
2023.02.09.
1. #6.0 Introduction (05:09)
소개
니코가 만든 api에 대한 소개
2. #6.1 AppBar (05:58)
앱바
key? elevation? backgroundColor? foregroundColor?
https://github.com/NewChoBo/toonflix/commit/c6bc5d49d029354a766f3394b296c773fba944e9
3. #6.2 Data Fetching (11:44)
데이터 불러오기
pub.dev 에서 http 검색, installing에서...
커맨드라인에서 설치 or pubspec.yaml에서
<code />
dependencies:
http: ^0.13.5
입력
await? async? future?
import에서 as로 이름 정해주면 맞춰서 함수 쓸 수 있음.
statecode가 200이면 요청 성공
4. #6.3 fromJson (09:59)
json 데이터 가져와서 변환
https://github.com/NewChoBo/toonflix/commit/d42a27ebb0fd3ec06d9dae1568f621f0f6414776
5. #6.4 Recap (06:09)
복습
==
이 위는 날라감. 깃허브에서라도 확인하자
2023.02.10.
6. #6.5 waitForWebToons (05:48)
뭔소리일까
저번시간엔 API로 데이터를 fetch 해서 JSON으로 된 데이터를 class로 바꾼 후
모든 클래스를 리스트에 넣어서 그 리스트를 반환했다.
그리고 거기서 나온 함수와 property를 static으로 바꿀 것.
HomeScreen을 StatefulWidget으로 바꾼다.
그리고 데이터 가져와서 어쩌고 저쩌고...
<java />
import 'package:flutter/material.dart';
import 'package:toonflix/models/webtoon_model.dart';
import 'package:toonflix/services/api_service.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
List<WebtoonModel> webtoons = [];
bool isLoading = true;
void waitForWebToons() async {
webtoons = await ApiService.getTodayToons();
isLoading = false;
setState(() {});
}
@override
void initState() {
super.initState();
waitForWebToons();
}
@override
Widget build(BuildContext context) {
print(webtoons);
print(isLoading);
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
elevation: 2, //음영(높낮이차)
foregroundColor: Colors.green,
backgroundColor: Colors.white,
centerTitle: true,
title: const Text(
"오늘의 웹툰",
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.w500,
),
),
),
);
}
}
지금 방식은 맘에 들지 않는데,
webtoons와 isLoading을 만들어야 하고 수동으로 await 해주고
isLoading도 false로 직접 해줘야 하고,..
일단 데이터가 없을때 화면이 뜨면 로딩화면을 보여주고, 데이터를 받고 나서 화면을 보여주게 할 것.
Future을 기다리는 더 좋은 방법? -> 다음 시간에..
https://github.com/NewChoBo/toonflix/commit/61190e5eafffec2360afd0f1586cfb5b18c26b8c
7. #6.6 FutureBuilder (07:05)
future을 기다리는 더 좋은 방법?
이전 영상에서는 데이터를 fetch해 State에 넣는 방법을 배웠다.
하지만 State는 최대한 사용하지 않는게 좋다(?)
Stateless 위젯으로 바꿔줌.
scaffold의 body에 FutureBuilder 넣음.
snapshot으로 Future의 상태를 알 수 있다.?
body에서 FutureBuilder로 나중에 올 데이터에 맞춰 build 작성???
??????
https://github.com/NewChoBo/toonflix/commit/e153c362a297243e937c735513478c5c65c45680
8. #6.7 ListView (11:59)
FutureBuilder는 future값을 기다리고, 데이터가 존재하는지 알려준다.
위 코드는 로딩되는 빙글빙글 보여줌.
ListView는 기본적으로 scroll view도 제공.
<java />
if (snapshot.hasData) {
return ListView(
//ListView를 사용해볼것
//기본 버전
children: [
for (var webtoon in snapshot.data!)
Text(
webtoon.title,
),
],
);
}
하지만 모든것을 로딩하는것은 단점.
사용자가 보고있는 사진이나 섹션만 로딩
한번에 로딩하면 메모리를 많이 사용하게됨.
계속 스크롤을 내릴 수 있는 무한스크롤같은 기능을 쓰면 결국 메모리가 죽을것.
그래서 다른 종류의 ListView 사용해볼 것.
ListView.builder : 더 최적화됨. 옵션도 많다
모든 아이템을 한번에 만드는 대신, 만들려는 아이템에 itemBuilder 함수를 실행한다.
...만들었던것도 지우고 화면에 나타날때 다시 만들어주는 모양이다.
https://github.com/NewChoBo/toonflix/commit/9b5407227ac135ca28d20ec8f205336b01e2e6f8
ListView.separated?
separatorBuilder 필요.
separatorBuilder은 Widget을 리턴하는 함수.
그냥 ListView.builder 처럼 필요하면 만들고 필요없어지면 지운다.
https://github.com/NewChoBo/toonflix/commit/a8e92de6a12adec909bda17f7db007f9f04c14ae
다음 시간에는 webtoon component 만든다.
9. #6.8 Webtoon Card (13:55)
웹툰카드?
itemBuilder은 ListView의 아이템을 만드는 역할을 한다. 만들어야 하는 아이템의 위치(숫자)=>인덱스를 받는다.
0~아이템의 총 갯수...
separatorBuilder : 아이템들 사이에 구분자를 넣어줌. 간격이 어떻게 될지. 구분자는 위젯, 이모지, sizedbox 다 됨.
ListView의 위에 공간을 주기 위해 Column안에 sizedbox를 넣어 만들건데 ListView의 높이가 무제한으로 측정되기 때문에 제한된 높이를 줘야 한다.
그를 위해 makeList를 Expanded로 감싸준다.
Expanded는 화면의 남는 공간을 차지하는 widget
clipBehavior : 자식의 부모 영역 침범 제어 방법
https://github.com/NewChoBo/toonflix/commit/0ee2234619ac6acb53a81ea32ae9000895d7a0b1
10. #6.9 Detail Screen (13:37)
세세한 화면?
사용자의 동작을 인식?
GestureDetector : 대부분 동작 감지 가능
onTap, onTapUp, onTapDown??
스크린 이동하는법?
Navigator? route?
네비게이터로 새 route를 push
https://github.com/NewChoBo/toonflix/commit/63858003d78c5dbe0e193ad09e894b1f3c377086
11. #6.10 Hero (04:58)
???
안드로이드에도 있는 기능인가봄 : https://nomadcoders.co/flutter-for-beginners/lectures/4169/comments/119144
Hero widget?
원래 있던 데이터를 재활용할때 원래 이미지가 움직이면 얼마나 멋있을까? Hero widget 쓰면 쉬움
Hero widget을 두 개의 화면에 각각 사용하고,
각각의 위젯에 tag 추가하면 flutter이 알아서 만들어준다.
Navigator.push로 사용자를 DetailScreen으로 보낼 때 Webtoon의 ID도 함께 보낸다.
https://github.com/NewChoBo/toonflix/commit/6e1b8b0e0f5638a91f154d2e71b013a39f6cc746
12. #6.11 Recap (05:30)
복습
GestureDetector로 여러 동작 감지 가능.
Navigator.push로 화면 전환 가능.
애니메이션으로 유저가 다음 화면으로 가는것처럼 느낌.
Hero는 두 화면 사이에 애니메이션을 준다.
tag가 같으면 화면 이동할때 사진을 새로 띄우는게 아니라 이동하는 애니메이션
다음시간은 detail에서 만화정보를 자세하게 띄워줄 것.
https://github.com/NewChoBo/toonflix/commit/6e1b8b0e0f5638a91f154d2e71b013a39f6cc746
13. #6.12 ApiService (10:15)
API URL에 Webtoon의 ID를 붙인 데이터 fetch?
url로 request 보내고, request 성공하면 string 받아서 json으로 변환.
그 json 받아서 변환...
https://github.com/NewChoBo/toonflix/commit/55b28b65a5d4dd884af5b73376487d391d294240
14. #6.13 Futures (07:48)
지난 시간엔 service method들을 만들었는데, ID로 웹툰정보 가져오거나 최신 에피소드...
우리가 HomeScreen가져온것과 비슷??
디테일스크린을 stateful widget으로.
widget.~~~의 이유는 별개의 클래스에서 작업하고 있기 때문에 widget을 붙여줘야 하는 것.(stateful은 변수저장 밖에서)
https://github.com/NewChoBo/toonflix/commit/019950d3b14aa6b35f65c417e0063988e8b3d061
15. #6.14 Detail Info (06:10)
정보 띄워주었음.
body에 children 하나씩 집어넣으면서...
16. #6.15 Episodes (15:45)
화면에 에피소드 정보 집어넣기...
지난시간에 Stateful Widget으로 변환한 이유는 initState 메소드가 필요했기 때문.
overflow는 padding을 SingleChildScrollView로 감싸면 된다.
https://github.com/NewChoBo/toonflix/commit/dcb4b32c3eed0b1b4117f5d21bf475892bf7e11d
코드챌린지
초록바탕에 흰 글씨 대신 초록 글씨에 초록 테두리?
버튼 자체는 색을 되돌리나봄
다음시간은 링크타고 브라우저로 들어가서 웹툰 읽을 수 있게 해줄 것.
박스 쉐도우도 사진처럼 넣어볼까?
-> https://github.com/NewChoBo/toonflix/commit/6cf191cd898663a2072fad09fa9f73b83ec9b159
17. #6.16 Url Launcher (12:31)
url 이동?
url_launcher 패키지 (pub.dev)
url_launcher은 Http url만 실행하는게 아니라, sms url이나 telephone url 등 도 실행할 수 있다.
Readme에 있는 코드 복붙 필요
안드로이드 : android/app/src/main/AndroidManifest.xml
ios : ios/Runner/info.plist
입력하고 나면 애뮬레이터 종료
failed to find the latest git commit date flutter 버그났었음. clean도 해보고 어쩌고 저쩌고 다 해봤는데,,,
<java />git config --global --add safe.directory C:/tools/flutter
뭔가 진전이 있는거같기도 하고...
위에 경로 설정해준 다음 clean -> pub 다운로드 하니까 고쳐진것같음.
다시 이어서...
hot reloading은 Dart 코드의 변경만 반영됨.
따라서 애뮬 껏다켜야함.
launchUrl?
https://github.com/NewChoBo/toonflix/commit/7f53b276c59463caea7b2d06290ddae7346c9d0e
18. #6.17 Favorites (17:10)
아마 사용자의 개인 DB(?)에 접근하는 그런 느낌이 되지 않을까 싶음.
휴대폰의 저장소에 데이터를 저장하는 법?
shared_preferences라는 패키지를 이용하면 된다.
(설치는 전에 하던것처럼 pub.dev에서.) 난 터미널에서
<code />
flutter pub add shared_preferences
작동방식 : 핸드폰 저장소와 connection 만들어야 함.
한줄로 getInstance해주고 나면 각기 다른 값과 다른 자료형을 저장할 수 있음. //key와 value형태로...
https://pub.dev/packages/shared_preferences
쓰기
<code />
// Obtain shared preferences.
final prefs = await SharedPreferences.getInstance();
// Save an integer value to 'counter' key.
await prefs.setInt('counter', 10);
// Save an boolean value to 'repeat' key.
await prefs.setBool('repeat', true);
// Save an double value to 'decimal' key.
await prefs.setDouble('decimal', 1.5);
// Save an String value to 'action' key.
await prefs.setString('action', 'Start');
// Save an list of strings to 'items' key.
await prefs.setStringList('items', <String>['Earth', 'Moon', 'Sun']);
읽기
<code />
// Try reading data from the 'counter' key. If it doesn't exist, returns null.
final int? counter = prefs.getInt('counter');
// Try reading data from the 'repeat' key. If it doesn't exist, returns null.
final bool? repeat = prefs.getBool('repeat');
// Try reading data from the 'decimal' key. If it doesn't exist, returns null.
final double? decimal = prefs.getDouble('decimal');
// Try reading data from the 'action' key. If it doesn't exist, returns null.
final String? action = prefs.getString('action');
// Try reading data from the 'items' key. If it doesn't exist, returns null.
final List<String>? items = prefs.getStringList('items');
우리가 하려는건 버튼을 누를때마다 좋아요를 누른 모든 ID의 리스트를 가져오고, 거기다가 웹툰ID를 넣어줄 것.
그럴꺼면 리스트보단 집합으로 하는게 나을듯?
새 패키지 설치하면 애뮬 껏다키기
initstate함수 내에서 함수 호출해 값을 바꿔도 setState는 또 따로 해줄 필요가 있다.
https://github.com/NewChoBo/toonflix/commit/f10950d32036b0f2658898620416682f0c626694
19. #6.18 Thank You (02:21)
ui 만들기
future로 api 데이터 가져오기
리스트 builder
웹뷰
사용자 휴대폰에 데이터 저장
을 배웠음.
틱톡 클론코딩에서는 firebase로 백엔드.
그 외에도 여러가지 배울것...
https://gamestory2.tistory.com/215
터미널에 flutter build apk --release --target-platform=android-arm64
...apk파일로 뽑아 보았지만...
아무래도, 권한허가 처리같은 부분을 안해서 그런가 켜면 무한로딩 걸리고 안풀리는 모습을 보인다.
https://happyguy81.tistory.com/151
안드로이드 인터넷 권한을 AndroidManifest.xml에서 허용 안해서 그럴지도?
uses-permission 넣고 다시 build해보았다.
잘 실행된다. ㅋ
웹 브라우저에서 안나오는 경우 : https://nomadcoders.co/flutter-for-beginners/lectures/4167/comments/115987
<java />
"dart.flutterRunAdditionalArgs": [
"--web-renderer",
"html"
],
를 settings.json 최하단에 추가해주면 되네요...
마우스 스크롤이 안될 경우
방법 1 : https://nomadcoders.co/flutter-for-beginners/lectures/4166/comments/118122
방법 2 : https://nomadcoders.co/flutter-for-beginners/lectures/4166/comments/121025
방법1 --> 테스트 안해봄
방법2 --> (Windows, Chrome, Edge, Android 동작 확인)
방법2 적용한 코드
https://github.com/NewChoBo/toonflix/commit/a1e75d03b22c07dcca855b1859fdfa552ddf7846
https://dajoonee.tistory.com/35
flutter config --enable-web 입력
엄청 안되길래 반쯤 포기하고있었는데 이렇게 하니까 된다...
https://ssscool.tistory.com/638
<java />
<base href="/toonflix.io/web/">
toonflix.io는 내 repository 이름
<깃허브에서 내 파일 위치> toonflix.io/web/index.html
newchobo.github.io/toonflix.io/web
이유는 모르겠으나, 화면비가 모바일 일때만 썸네일들이 정상 출력되는것으로 보임.
모바일도 다 되는게 아님...
일단 반응형은 나오는것 같고,
일반 데스크톱 안됨.
크롬 지원하는것 중에 추려보면
아이폰중에 되는 것 :
아이패드중에 되는 것 :
안드로이드 안되는 것 :
Surface Pro 7 : 안됨
Surface Duo : 됨
Nest Hub : 됨
Nest Hub Max : 안됨
반응형 화면비를 아이폰꺼로 했을땐 나왔음. 화면비만의 문제는 아닌듯. 다른 요인이 있을텐데...
배포버전 말고, 디버깅하면서 크롬브라우저로 실행할때는 잘 나온다... 휴대폰 하든 데스크탑버전 하든...
'공부 > Flutter' 카테고리의 다른 글
Flutter 로 웹툰 앱 만들기 #5 POMODORO APP (0) | 2023.02.05 |
---|---|
Flutter 로 웹툰 앱 만들기 #4 STATEFUL WIDGETS (0) | 2023.02.04 |
Flutter 로 웹툰 앱 만들기 #3 UI CHALLENGE (0) | 2023.02.03 |
Flutter 로 웹툰 앱 만들기 #2 HELLO FLUTTER (0) | 2023.02.02 |
Flutter 로 웹툰 앱 만들기 #1 INTRODUCTION (0) | 2023.02.02 |