| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 | 31 |
- Kotlin
- API
- App
- chown -R
- android studio
- 컴공
- chown
- flutter
- mac os 권한
- kotlin-android-extensions
- import안됨
- login_btn
- 코틀린
- import
- 앱개발
- dart
- 맥북 권한
- HTTP
- chmod
- mac permission denied
- 앱
- Today
- Total
Milan Dev
#Flutter. EPL 일정 앱 개인 프로젝트 ep.1 팀 선택화면 만들기 본문
계속 배포에 실패하는 프로젝트들을 뒤로하고 혼자 Flutter로 제가 흥미를 가지고 있는 주제로 앱을 만들기로 했습니다.
이번 프로젝트에 목표는 어떻게든 배포까지 성공적으로 할 수 있도록 하는 것입니다.
뭔가 제가 좋아하는(해외축구) 주제로 프로젝트를 진행하려 하니 더 설레는 맘이 있더라구요 ㅎㅎ
먼저 이번 프로젝트의 주제는 EPL 팀중 선호하는 팀을 고르면 경기 일정을 알려주고 알림을 등록하면 백그라운드로 경기 전 사용자에게 알림을 보내줄 수 있는 백그라운드 알림을 기본 기능으로 생각했습니다.
자세한 코드들은 깃허브를 확인해주세요!(미완성에 계속 업데이트 될 것 같습니다.)
먼저 로그인이나 회원가입은 굳이 필요하단 생각이 들지 않아 빠르게 생략하고 응원하는 팀을 고를 정보를 받아와야 했습니다.
아무래도 해외축구다 보니까 국내에선 open api 를 찾을 수 없어 해외에 축구 데이터 사이트를 찾아봤습니다.
https://www.football-data.org/
football-data.org - ur src for machine readable football data
Purpose of the project football-data.org provides football data and statistics (live scores, fixtures, tables, squads, lineups/subs, etc.) in a machine-readable way. I won't announce how awesome football-data is, you're welcome to find out by yourself (or
www.football-data.org
여기 football-data 사이트에선 전 세계의 리그 경기, 컵경기, 국제경기등 거의 모든 축구 데이터를 사용할 수 있습니다.
먼저 회원가입을 하면 이메일로 X-Auth-Token 을 발급해줍니다.

발급받은 토큰은 football-data 사이트에서 로그인을 할때 사용되며 모든 API 통신에 Header에 넣어 사용해야합니다.

Documentation에서 사용할 수 있는 API 명세서가 나와 있으니 사용하시면 될 것 같습니다.

더 많은 기능은 유료지만 일단 저에게 필요한 기능은 무료 버전에도 있기때문에 구매는 하지 않고 진행하겠습니다~
import 'package:flutter/material.dart';
import 'package:myfootball/screens/home_screen.dart';
import 'package:myfootball/services/api_service.dart';
void main() {
// ApiService().getMatchSample();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeScreen(),
);
}
}
먼저 프로젝트를 생성해주고 main.dart에선 HomeScreen()을 가져오기로 했습니다.
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:myfootball/widgets/team_list_widget.dart';
class HomeScreen extends StatelessWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
elevation: 2,
backgroundColor: Colors.white,
foregroundColor: Colors.blue,
title: const Text(
"팀을 선택해주세요.",
style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600),
),
),
body: TeamListWidget(),
);
}
}
그리고 HomeScreen()은 Appbar와 팀을 고를 수 있는 TeamListWidget()을 렌더링 하도록 했습니다.
이제 팀 선택을 위한 로고를 화면에 띄우기 위해 TeamListWidget()을 만들어야 하는데 이를 위해선 API로 데이터를 가져오는 작업이 필요합니다.
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:myfootball/models/match_model.dart';
class ApiService {
final String baseUrl = "https://api.football-data.org/v4";
final String matchSample = "competitions/PL/standings";
Future<MatchModel> getMatchSample() async {
final url = Uri.parse('$baseUrl/$matchSample');
final response = await http.get(
url,
headers: {'X-Auth-Token': '이메일로 발급받은 API키를 여기에 넣어주세요!'},
);
if (response.statusCode == 200) {
var jsonResponse = jsonDecode(response.body);
print("parsing successes");
return MatchModel.fromJson(jsonResponse);
}
print("$baseUrl/$matchSample");
print(response.statusCode);
throw Error();
}
}
이건 API 통신을 위해 만든 api_service.dart 코드입니다.
API 통신을 위한 비동기 작업 코드를 만들었습니다. 성공적으로 통신한다면 parsing successes를 출력하고 데이터를 받아와 jsonResponse에 저장합니다.
받아온 데이터는 파싱하여 필요한 곳에 써주어야 하는데 json 파싱을 위해서 응답값에 맞는 모델을 만들어 주어야 합니다.

여기에 코드를 올리기엔 모델의 길이가 너무 길어서 자세한 코드는 깃허브를 확인해주세요..
이제 API를 통해 받아온 데이터를 원하는 화면에 적용하기만 하면 끝입니다!!
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:myfootball/services/api_service.dart';
import 'package:myfootball/models/match_model.dart';
class TeamListWidget extends StatefulWidget {
@override
_TeamListWidgetState createState() => _TeamListWidgetState();
}
class _TeamListWidgetState extends State<TeamListWidget> {
late Future<MatchModel> futureMatchModel;
@override
void initState() {
super.initState();
futureMatchModel = ApiService().getMatchSample();
}
@override
Widget build(BuildContext context) {
return FutureBuilder<MatchModel>(
future: futureMatchModel,
builder: (context, snapshot) {
if (snapshot.hasData) {
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemCount: snapshot.data!.standings[0].table.length,
itemBuilder: (context, index) {
return Card(
child: Column(
children: <Widget>[
SizedBox(
height: 20,
),
Container(
height: 120,
width: 120,
child: snapshot.data!.standings[0].table[index].team.crest
.endsWith('.svg')
? SvgPicture.network(
snapshot
.data!.standings[0].table[index].team.crest,
fit: BoxFit.cover,
)
: Image.network(
snapshot
.data!.standings[0].table[index].team.crest,
fit: BoxFit.cover,
),
),
SizedBox(
height: 10,
),
Text(snapshot.data!.standings[0].table[index].team.name),
],
),
);
},
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return CircularProgressIndicator();
},
);
}
}
TeamListWidget()는 받아온 데이터 중 팀 이름과 앰블럼을 찾아 그리드 형식의 리스트로 구성했습니다.
(앰블럼은 svg와 png를 랜더링하는데 문제가 좀 있었는데 이건 다음에 따로 포스팅하겠습니다.)
팀 앰블럼을 리스트로 받아왔습니다!

앱 출시까지 화이팅하겠습니다.
봐주셔서 감사합니다!
'Flutter' 카테고리의 다른 글
| #Flutter. EPL 일정 앱 개인 프로젝트 ep.2 선택된 팀 화면 구현중 (0) | 2024.01.13 |
|---|---|
| #Flutter. SVG(벡터이미지) URL, flutter에서 사용하기. (0) | 2024.01.12 |
| #Flutter. shared preferences (1) | 2023.12.26 |
| #Flutter. Api service: 파라미터를 갖는 메소드 초기화 (0) | 2023.12.25 |
| #Flutter. GestureDetector: 사용자 동작감지 위젯 (1) | 2023.12.23 |