newChobo

크롬이 한번 튕겨서 저장이 안되고 다 날라감... ㅅㅂ

 

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이면 요청 성공

import 'package:http/http.dart' as http;
...
Future<List<WebtoonModel>> getTodayToons() async {
...
final response = await http.get(url); //데이터를 받을때까지 기다려야 함
...
if (response.statusCode == 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값을 기다리고, 데이터가 존재하는지 알려준다.

return const Center(
            child: CircularProgressIndicator(),

위 코드는 로딩되는 빙글빙글 보여줌.

 

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도 해보고 어쩌고 저쩌고 다 해봤는데,,,

https://stackoverflow.com/questions/73047675/flutter-failed-to-find-the-latest-git-commit-date-versioncheckerror-command-ex

 

<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로 백엔드.

그 외에도 여러가지 배울것...

 

app-release.apk
6.53MB

https://gamestory2.tistory.com/215

터미널에 flutter build apk --release --target-platform=android-arm64

...apk파일로 뽑아 보았지만...

아무래도, 권한허가 처리같은 부분을 안해서 그런가 켜면 무한로딩 걸리고 안풀리는 모습을 보인다.

 

https://happyguy81.tistory.com/151

안드로이드 인터넷 권한을 AndroidManifest.xml에서 허용 안해서 그럴지도?

 

    package="com.example.toonflix">

    <uses-permission android:name="android.permission.INTERNET" />

   <application

uses-permission 넣고 다시 build해보았다.

 

app-release.apk
6.53MB

 

잘 실행된다. ㅋ

 

웹 브라우저에서 안나오는 경우 : 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 : 안됨

 

반응형 화면비를 아이폰꺼로 했을땐 나왔음. 화면비만의 문제는 아닌듯. 다른 요인이 있을텐데...

배포버전 말고, 디버깅하면서 크롬브라우저로 실행할때는 잘 나온다... 휴대폰 하든 데스크탑버전 하든...

 

배포 링크 : https://newchobo.github.io/toonflix.io/web/#/

profile

newChobo

@새로운뉴비

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!