Future 란?
지금은 없지만 미래에 작업이 수행되어 결과를 나타낼 것이라는 상태를 나타냄.
future 는 비동기 작업의 결과를 나타내며 미완료(데이터 value를 생성하기 전) 또는 완료(데이터 value 생성)의 두 가지 상태를 가질 수 있다.
미완료 : 비동기 함수를 호출하면 데이터 value 가 생성되기 전인 완료되지 않은 미래가 반환된다. future 는 비동기 함수의 작업이 완료되거나 오류가 발생하기를 기다리고 있다.
완료 : 비동기 작업이 성공하면 future 를 데이터 value 로 반환한다.
작성한 파일 목록 입니다.
1. pubspec.yaml
2. HttpService.dart
3. FutureScrollPage.dart
1. pubspec.yaml
http 통신을 사용하려면 일단 pubspec.yaml 파일에 dependencies 를 추가해줘야 하는데요!
여기서 http 의 버전을 확인하여 추가해줍니다!
flutter: 와 같은 라인에 http: 를 추가해주어야해요~~!
http: ^0.13.3
=============== pubspec.yaml ===============
...
dependencies:
flutter:
sdk: flutter
http: ^0.13.3
...
그런데 버전을 명시하지 않고 그냥
http:
이렇게만 입력하면 현재 최신버전을 사용하겠다는 것이라고 하네요!
=============== pubspec.yaml ===============
...
dependencies:
flutter:
sdk: flutter
http:
...
2. HttpService.dart
http 통신을 통해 데이터를 가져오는 부분입니다.
'package:http/http.dart' as http 를 import 해서 yaml 파일에 dependencies 추가한 http 를 사용하도록 해줍니다.
그리고 json 형태로 변환하기 위해 'dart:convert' 를 import 하여 json.decode() 를 사용하였습니다.
import 'dart:convert';
import 'package:flutter_application_1/model/BearItem.dart';
import 'package:http/http.dart' as http;
class HttpService {
Future<http.Response> fetch() async {
String url = 'http://-----:8080/MyTestProj/index.jsp';
Uri uri = Uri.parse(url);
return http.get(uri);
}
Future<BearList> fetchBear() async {
String url = 'http://-----:8080/MyTestProj/index.jsp';
Uri uri = Uri.parse(url);
var response = await http.get(uri);
var statusCode = response.statusCode;
var headers = response.headers;
var body = json.decode(response.body);
print('[$runtimeType] fetchBear - statusCode : $statusCode');
print('[$runtimeType] fetchBear - headers : $headers');
print('[$runtimeType] fetchBear - body : $body');
if (response.statusCode == 200) {
return BearList.fromJson(body);
} else {
throw Exception(' Failed to load Bear ');
}
}
}
이 부분은 아래의 링크를 참고하여 작성하였습니다.
https://flutter.dev/docs/cookbook/networking/fetch-data
3. FutureScrollPage.dart
기존에 dart 파일 상단에 하드코딩으로 이용했던 json 데이터를 http 통신을 통해 가져오겠습니다.
그리고 FloatingActionButton 을 통해 제일 상단/하단으로 강제 스크롤하는 코드를 사용하였습니다.
FutureBuilder 사용
FutureBuilder<BearList>( //FutureBuilder 를 사용하여 데이터 가져오기
future: HttpService().fetchBear(), //http 통신하는 메소드
builder: (context, snapshot) {
if(snapshot.hasData) { //작업이 완료 시 - snapshot 을 통해 데이터 반환
return bodyWidget(snapshot.data!);
} else { //작업이 미완료시 - ProgressIndicator 위젯 표시
return Center(
child: CircularProgressIndicator(),
);
}
},
),
FutureBuilder 는 위의 형태를 사용합니다.
scrollController 를 사용한 강제 스크롤
WidgetsBinding.instance!.addPostFrameCallback((timeStamp) { //이 프레임에서 가장 나중에 실행되겠다
_scrollController.animateTo(
_scrollController.position.minScrollExtent, //minScrollExtent:제일 상단, maxScrollExtent:제일 하단
duration: Duration(milliseconds: 200),
curve: Curves.easeInOut,
);
});
이 형태를 사용합니다.
FutureScrollPage.dart 전체소스
import 'package:flutter/material.dart';
import 'HttpService.dart';
import 'model/BearItem.dart';
class FutureScrollPage extends StatefulWidget {
const FutureScrollPage({
Key? key,
}) : super(key: key);
@override
_FutureScrollPageState createState() => _FutureScrollPageState();
}
class _FutureScrollPageState extends State<FutureScrollPage> {
late ScrollController _scrollController = ScrollController();
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('FutureScrollPage'),
),
floatingActionButton: Container(
alignment: Alignment.bottomCenter,
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: [
//FloatingActionButton 1 : 가장 위로 강제 스크롤
FloatingActionButton(
onPressed: () {
WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
_scrollController.animateTo(
_scrollController.position.minScrollExtent,
duration: Duration(milliseconds: 200),
curve: Curves.easeInOut,
);
});
},
child: Icon(Icons.arrow_upward),
),
//FloatingActionButton 2 : 가장 아래로 강제 스크롤
FloatingActionButton(
onPressed: () {
WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
_scrollController.animateTo(
_scrollController.position.maxScrollExtent,
duration: Duration(milliseconds: 200),
curve: Curves.easeInOut,
);
});
},
child: Icon(Icons.arrow_downward),
),
],
),
),
body: FutureBuilder<BearList>( //FutureBuilder 를 사용하여 데이터 가져오기
future: HttpService().fetchBear(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return bodyWidget(snapshot.data!);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
),
);
}
Widget bodyWidget(BearList bearList) {
return Container(
child: ListView.separated(
controller: _scrollController,
separatorBuilder: (BuildContext context, int index) => const Divider(
color: Colors.grey,
height: 4,
), //separatorBuilder : item과 item 사이에 그려질 위젯 (개수는 itemCount -1 이 된다)
itemCount: bearList.list!.length, //리스트의 개수
itemBuilder: (BuildContext context, int index) {
//리스트의 반목문 항목 형성
return Container(
height: 80,
decoration: BoxDecoration(
color: Colors.pink[index * 100],
),
child: Row(
children: [
Container(
width: 50,
alignment: Alignment.center,
child: Text(
'$index',
style: TextStyle(
fontSize: 20,
),
),
),
Image.asset(
bearList.list!.elementAt(index).image!,
),
Expanded(
child: Container(
alignment: Alignment.center,
child: Text(
bearList.list!.elementAt(index).name!,
style: TextStyle(
fontSize: 20,
),
),
),
),
],
),
);
},
),
);
}
}
결과화면
감사합니다.
'📘 Flutter' 카테고리의 다른 글
[Flutter] 다양한 위젯(Widget) 사용하기 - Dialog, DatePicker, TimePicker, SnackBar, GestureDetector, InkWell (0) | 2021.07.17 |
---|---|
[Flutter] TextField 사용하기 (3) | 2021.07.07 |
[Flutter] 탭바(TabBar) 사용하기 (0) | 2021.07.06 |
[Flutter] CarouselSlider (2) | 2021.06.27 |
[Flutter] 카드(Card) 위젯 사용하기 (0) | 2021.06.27 |