ChuckNorris 라는 19세 농담을 던져주는 json api가 있습니다.
그 rest api를 사용해서 화면에 뿌려지는 간단한 어플을 만들어보도록 하겠습니다.
우선 JSON To Dart Class (JsonToDartClass)를 설치하여줍니다.
이런게 플러그인으로 있는지 몰랐는데.. 매우 좋습니다!!! 짱짱 json 형식을 dart class 로 바꾸어집니다.
원하는대로 바꾸어지지 않을 수 있지만 몇개만 추가하면되서 무조건 이 방식이 좋습니다.
먼저 provider, http, translator 이렇게 3가지를 추가해줍니다.
provider 패턴을 이용할것이고 http로 json response를 받을것이고 translator로 영어로된것을 한글로 번역할것입니다.
파일트리입니다.
저는 연습장 정도로만 쓰는 프로젝트에서 만들어서 패키지 이름이 flutter_note 입니다.
pubspec.yaml
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.0
provider: ^4.0.5+1 //추가
http: ^0.12.0+4 //추가
translator: ^0.1.5 //추가
dev_dependencies:
flutter_test:
sdk: flutter
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_note/providers/ChuckyProvider.dart';
import 'package:flutter_note/view/init/initializeProviderDataScreen.dart';
import 'package:provider/provider.dart';
import 'package:translator/translator.dart';
void main() async {
run();
// var translation = await translator.translate("hello", to: 'ko');
// print(translation);
// print(await "example".translate(to: 'ko'));
// WidgetsFlutterBinding.ensureInitialized();
// SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
// .then((_) {
// run();
// });
}
void run() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
MyApp();
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => ChuckyProvider()),
],
child: MaterialApp(
color: Colors.white,
home: InitializeProviderDataScreen(),
),
);
}
@override
void dispose() {
super.dispose();
}
}
initializeProviderDataScreen.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_note/models/chuck_random.dart';
import 'package:flutter_note/providers/ChuckyProvider.dart';
import 'package:flutter_note/view/chucky/chuck_random_view.dart';
import 'package:provider/provider.dart';
class InitializeProviderDataScreen extends StatefulWidget {
@override
_InitializeProviderDataScreenState createState() =>
_InitializeProviderDataScreenState();
}
class _InitializeProviderDataScreenState
extends State<InitializeProviderDataScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Center(
child: _loadChuckyCategories(),
),
);
}
Widget _loadChuckyCategories() {
return FutureBuilder(
future: Provider.of<ChuckyProvider>(context, listen: true)
.fetchChuckyRandom(),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.active:
case ConnectionState.waiting:
return getChuckNorris();
case ConnectionState.done:
if (snapshot.hasError) {
return Text('ConnectionState.done / snapshot.hasError',
textAlign: TextAlign.center);
} else {
return ChuckRandomView(chuckRandom: snapshot.data);
}
}
return getChuckNorris();
},
);
}
Widget getChuckNorris() {
return Container(
width: MediaQuery.of(context).size.width,
child: Padding(
padding: const EdgeInsets.all(22.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 240,
),
Image.asset(
'assets/images/chucknorris_logo.png',
width: 280,
height: 280,
),
Expanded(child: SizedBox())
],
),
),
);
}
}
chuck_random_view.dart
import 'package:flutter/material.dart';
import 'package:flutter_note/models/chuck_random.dart';
import 'package:flutter_note/providers/ChuckyProvider.dart';
import 'package:provider/provider.dart';
import 'package:translator/translator.dart';
class ChuckRandomView extends StatefulWidget {
ChuckRandom chuckRandom;
ChuckRandomView({this.chuckRandom});
@override
_ChuckRandomViewState createState() =>
_ChuckRandomViewState(chuckRandom: chuckRandom);
}
class _ChuckRandomViewState extends State<ChuckRandomView> {
ChuckRandom chuckRandom;
var chuckKO = '';
_ChuckRandomViewState({this.chuckRandom});
@override
void initState() {
super.initState();
translateText(chuckRandom.value);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: MediaQuery.of(context).size.width,
child: Padding(
padding: const EdgeInsets.all(22.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(child: SizedBox()),
Image.asset(
'assets/images/chucknorris_logo.png',
width: 280,
height: 200,
),
chuckTextWidget(chuckRandom.value),
SizedBox(
height: 30,
),
chuckTextWidget(chuckKO),
Expanded(child: SizedBox()),
FlatButton(
color: Colors.blue,
textColor: Colors.white,
padding: EdgeInsets.all(8.0),
splashColor: Colors.blueAccent,
onPressed: () async {
ChuckRandom fetchChuckRandom =
await Provider.of<ChuckyProvider>(context, listen: false)
.fetchChuckyRandom();
translateText(fetchChuckRandom.value);
chuckRandom = fetchChuckRandom;
},
child: Text(
"Shot",
style: TextStyle(fontSize: 20.0),
),
),
],
),
),
),
);
}
translateText(text) async {
var translation = await GoogleTranslator().translate(text, to: 'ko');
setState(() {
chuckKO = translation.text;
});
}
Widget chuckTextWidget(text) {
return Text(
text,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontSize: 16,
),
);
}
}
commons.dart
import 'dart:convert';
import 'package:http/http.dart' as http;
class Commons {
///jokes/random
static const baseURL = "https://api.chucknorris.io";
static dynamic returnResponse(http.Response response) {
switch (response.statusCode) {
case 200:
var responseJson = jsonDecode(response.body.toString());
print(responseJson);
return responseJson;
case 400:
print('400 error');
return response.body.toString();
case 401:
case 403:
print('400 or 403 error');
return response.body.toString();
case 500:
print('500 error');
return response.body.toString();
default:
print('case default . error');
return response.body.toString();
}
}
}
ChuckyProvider.dart
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter_note/models/chuck_random.dart';
import 'package:flutter_note/utils/commons.dart';
import 'package:http/http.dart' as http;
import 'package:translator/translator.dart';
class ChuckyProvider extends ChangeNotifier {
ChuckRandom chuckRandom;
///jokes/random
Future<ChuckRandom> fetchChuckyRandom() async {
try {
final response =
await http.get((Commons.baseURL + '/jokes/random'), headers:{
"Accept": "application/json",
"content-type": "application/json",
});
if(response.statusCode == 200){
chuckRandom =ChuckRandom.fromJson(Commons.returnResponse(response));
return chuckRandom;
} else {
return null;
}
} on Exception {
print('fetch ChuckyRandom() exception');
return null;
}
}
}
ChuckRandom 클래스는 json to dart class 를 사용해서 만든것입니다!
아까 플러그인을 설치하였으면 상단에 Generate가 보일것입니다.
클릭하시고
적어주면 생성됩니다
chuck_random.dart
import 'package:translator/translator.dart';
class ChuckRandom {
final List<Object> categories;
final String createdAt;
final String iconUrl;
final String id;
final String updatedAt;
final String url;
final String value;
ChuckRandom({
this.categories,
this.createdAt,
this.iconUrl,
this.id,
this.updatedAt,
this.url,
this.value,
});
factory ChuckRandom.fromJson(Map<String, dynamic> json) {
return ChuckRandom(
categories: json['categories'] != null
? new List<String>.from(json['categories'])
: null,
createdAt: json['created_at'] ?? '',
iconUrl: json['icon_url'] ?? '',
id: json['id'] ?? '',
updatedAt: json['updated_at'] ?? '',
url: json['url'] ?? '',
value: json['value'] ?? '',
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['created_at'] = this.createdAt;
data['icon_url'] = this.iconUrl;
data['id'] = this.id;
data['updated_at'] = this.updatedAt;
data['url'] = this.url;
data['value'] = this.value;
if (this.categories != null) {
data['categories'] = this.categories;
}
return data;
}
}
MultiProvider 로 ChangeNotifierProvider들을 리스트에 담아줍니다.
ChangeNofifierProvider에 create 클래스들은 모두 ChangeNotifier 를 extends 하고있습니다.
feacth 해서 내려오는 값들을 snapshot의 상태를 확인해서 hasError가 아닌경우(hasData) 화면 뿌릴 위젯을 만듭니다.
to: 'ko' 는 Korea 입니다. 변경가능한 언어 리스트인데 골라서 변경해줘도 됩니다!
static final _langs = {
'auto': 'Automatic',
'af': 'Afrikaans',
'sq': 'Albanian',
'am': 'Amharic',
'ar': 'Arabic',
'hy': 'Armenian',
'az': 'Azerbaijani',
'eu': 'Basque',
'be': 'Belarusian',
'bn': 'Bengali',
'bs': 'Bosnian',
'bg': 'Bulgarian',
'ca': 'Catalan',
'ceb': 'Cebuano',
'ny': 'Chichewa',
'zh-cn': 'Chinese Simplified',
'zh-tw': 'Chinese Traditional',
'co': 'Corsican',
'hr': 'Croatian',
'cs': 'Czech',
'da': 'Danish',
'nl': 'Dutch',
'en': 'English',
'eo': 'Esperanto',
'et': 'Estonian',
'tl': 'Filipino',
'fi': 'Finnish',
'fr': 'French',
'fy': 'Frisian',
'gl': 'Galician',
'ka': 'Georgian',
'de': 'German',
'el': 'Greek',
'gu': 'Gujarati',
'ht': 'Haitian Creole',
'ha': 'Hausa',
'haw': 'Hawaiian',
'iw': 'Hebrew',
'hi': 'Hindi',
'hmn': 'Hmong',
'hu': 'Hungarian',
'is': 'Icelandic',
'ig': 'Igbo',
'id': 'Indonesian',
'ga': 'Irish',
'it': 'Italian',
'ja': 'Japanese',
'jw': 'Javanese',
'kn': 'Kannada',
'kk': 'Kazakh',
'km': 'Khmer',
'ko': 'Korean',
'ku': 'Kurdish (Kurmanji)',
'ky': 'Kyrgyz',
'lo': 'Lao',
'la': 'Latin',
'lv': 'Latvian',
'lt': 'Lithuanian',
'lb': 'Luxembourgish',
'mk': 'Macedonian',
'mg': 'Malagasy',
'ms': 'Malay',
'ml': 'Malayalam',
'mt': 'Maltese',
'mi': 'Maori',
'mr': 'Marathi',
'mn': 'Mongolian',
'my': 'Myanmar (Burmese)',
'ne': 'Nepali',
'no': 'Norwegian',
'ps': 'Pashto',
'fa': 'Persian',
'pl': 'Polish',
'pt': 'Portuguese',
'pa': 'Punjabi',
'ro': 'Romanian',
'ru': 'Russian',
'sm': 'Samoan',
'gd': 'Scots Gaelic',
'sr': 'Serbian',
'st': 'Sesotho',
'sn': 'Shona',
'sd': 'Sindhi',
'si': 'Sinhala',
'sk': 'Slovak',
'sl': 'Slovenian',
'so': 'Somali',
'es': 'Spanish',
'su': 'Sundanese',
'sw': 'Swahili',
'sv': 'Swedish',
'tg': 'Tajik',
'ta': 'Tamil',
'te': 'Telugu',
'th': 'Thai',
'tr': 'Turkish',
'uk': 'Ukrainian',
'ur': 'Urdu',
'uz': 'Uzbek',
'vi': 'Vietnamese',
'cy': 'Welsh',
'xh': 'Xhosa',
'yi': 'Yiddish',
'yo': 'Yoruba',
'zu': 'Zulu'
};
앱에 빌드하고 나오는 말들이 재미있어서 앱에 빌드하고 심심할때 봐도 괜찮을꺼같아요!
구글번역이라 번역이 잘 되지는 않습니다..
'📱Mobile > 🔥Flutter' 카테고리의 다른 글
[Flutter] 플러터 http GET, POST 사용하기, 요청(Request), 응답(Response) (197) | 2023.07.04 |
---|---|
flutter 프로그레스바 progress bar circle progress bar example (0) | 2021.01.08 |
flutter secure storage, 자동로그인, android KeyStore example (0) | 2021.01.07 |
[Flutter] provider + [Change Notifier] 를 사용한 Provider Pattern example (0) | 2021.01.06 |
[Flutter] 기초가 되는 StreamBuilder BLOC 패턴, StreamSubscription, yield example (0) | 2021.01.06 |