구글링이나 GitHub 샘플코드를 받아서 보면 Null Safety 이전과 이후의 버전에 따라 동작이 되기도 하고 안되기도 하더라.
라이브러리 버전을 최신버전으로 변경해보면 에러가 발생하는 것이 http, dio 부분에서 걸리는 거 같아서
dio 라이브러리에 대한 이해 부족으로 소스코드 변경에 시간 낭비를 하는 거 같아서 학습해 두고자 한다.
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
http: ^0.13.4 # 0.12.2 null safety 이전, 최신 버전 0.13.4
dio: ^4.0.6 # 3.0.10 null safety 이전, 최신 버전 4.0.6
|
main.dart 파일 import 사항
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:dio/dio.dart';
|
android/app/src/main/AndroidManifest.xml 파일 추가 사항
- 추가 안해도 개발 모드에서 잘 동작하는 걸 확인했다.
<uses-permission android:name="android.permission.INTERNET" />
|
서버에서 데이터 가져오고 파싱처리하는 코드
class _MyHomePageState extends State<MyHomePage> {
Future getServerDataWithHttp() async {
try {
var jsonString = await http.get(
Uri.parse('https://www.abc.com/androidSample/getData_Flutter.php'));
if (jsonString.statusCode == 200) {
print(jsonString);
var resp = jsonDecode(jsonString.body);
print(resp);
UserResult userResult = UserResult.fromJson(resp);
for (User user in userResult.result) {
print(user.userNM);
}
}
} catch (e) {
print('error : ${e}');
}
}
Future getServerDataWithDio() async {
String url = 'https://www.abc.com/androidSample/getData_Flutter.php';
BaseOptions options = BaseOptions(
baseUrl: 'https://www.abc.com',
connectTimeout: 3000,
receiveTimeout: 3000,
);
Dio dio = Dio(options);
try {
Response resp = await dio.get(
"/androidSample/getData_Flutter.php",
//queryParameters: {"search": "dio"},
);
print("Response:");
print("Status: ${resp.statusCode}");
print("Header:\n${resp.headers}");
print("Data:\n${resp.data}");
UserResult userResult = UserResult.fromJson(resp.data);
for (User user in userResult.result) {
print(user.userNM);
}
} catch (e) {
print("Exception: $e");
}
}
@override
void initState() {
super.initState();
getServerDataWithHttp();
getServerDataWithDio();
}
@override
Widget build(BuildContext context) { }
|
서버에서 가져온 JSON 데이터 구조
{result: [
{idx: 1, userNM: 개발자, mobileNO: 01000010001, telNO: 0234560001, photo: 1.jpg},
{idx: 2, userNM: 이정은, mobileNO: 01001230001, telNO: , photo: 2.jpg},
{idx: 3, userNM: 김홍길, mobileNO: 01001230002, telNO: , photo: }
]
}
|
class UserResult {
final List<User> result;
UserResult({required this.result});
factory UserResult.fromJson(Map<String, dynamic> parsedJson) {
var list = parsedJson['result'] as List;
List<User> usersList = list.map((i) => User.fromJson(i)).toList();
return UserResult(
result: usersList,
);
}
}
class User {
final int idx;
final String userNM;
final String mobileNO;
final String telNO;
final String photo;
User(
{required this.idx,
required this.userNM,
required this.mobileNO,
required this.telNO,
required this.photo});
factory User.fromJson(Map<String, dynamic> parsedJson) {
return User(
idx: parsedJson['idx'],
userNM: parsedJson['userNM'],
mobileNO: parsedJson['mobileNO'],
telNO: parsedJson['telNO'],
photo: parsedJson['photo'],
);
}
Map<String, dynamic> toJson() => {
"idx": idx,
"userNM": userNM,
"moboileNO": mobileNO,
"telNO": telNO,
"photo": photo,
};
}
|
factory는 싱글톤 패턴을 사용할 때 쓰는 예약어이다.
dart 공식문서에 새로운 인스턴스를 생성하지 않는 생성자를 구현할 때 factory 키워드를 사용하라고 명시되어 있다.
factory 의 특징
- 이전에 이미 생성된 인스턴스가 있다면 원래 값을 return하여 재사용한다.
- 하나의 클래스에서 하나의 인스턴스만 사용한다.
- 서브 클래스를 리턴할 때 사용할 수 있다.
- factory 생성자에서는 this에 접근할 수 없다.
서버에서 넘겨주는 데이터 형식을 아래와 같이 JSON 배열 데이터로 변경했다.
[
{idx: 1, userNM: 개발자, mobileNO: 01000010001, telNO: 0234560001, photo: 1.jpg},
{idx: 2, userNM: 이정은, mobileNO: 01001230001, telNO: , photo: 2.jpg},
{idx: 3, userNM: 김홍길, mobileNO: 01001230002, telNO: , photo: }
]
|
DIO를 이용해 데이터를 변환하는 로직
Future getServerDataWithDio() async {
BaseOptions options = BaseOptions(
baseUrl: 'https://www.abc.com',
connectTimeout: 3000,
receiveTimeout: 3000,
);
Dio dio = Dio(options);
try {
Response resp = await dio.get(
"/androidSample/getData_Flutter.php",
//queryParameters: {"search": "dio"},
);
print("Response:");
print("Status: ${resp.statusCode}");
print("Header:\n${resp.headers}");
print("Data:\n${resp.data}");
List<User> users = resp.data.map<User>((parsedJson) {
return User.fromJson(parsedJson);
}).toList();
for (User user in users) {
print(user.userNM);
}
} catch (e) {
print("Exception: $e");
}
}
|
POST 방식으로 데이터 통신을 할 경우 코드 예제이다.
formData 변수 사용법으로 사용하니까 제대로 동작되더라.
Future getServerDataWithDio() async {
BaseOptions options = BaseOptions(
baseUrl: 'https://www.abc.com',
connectTimeout: 3000,
receiveTimeout: 3000,
);
Dio dio = Dio(options);
var formData = FormData.fromMap({
"search": "이정은",
});
try {
Response resp = await dio.post(
"/androidSample/putData_Flutter.php",
data: formData,
);
// print("Response:");
// print("Status: ${resp.statusCode}");
// print("Header:\n${resp.headers}");
print("Data:\n${resp.data}");
// UserResult userResult = UserResult.fromJson(resp.data);
List<User> users = UserResult.fromJson(resp.data).result;
for (User user in users) {
print(user.userNM);
}
} catch (e) {
print("Exception: $e");
}
}
|
이해를 돕기 위해 서버 코드에 사용한 PHP 코드를 첨부한다.
<?php
if(!isset($_SESSION)) {
session_start();
}
//ini_set("display_startup_errors", 1);
//ini_set("display_errors", 1);
//error_reporting(E_ALL);
// 파일을 직접 실행하면 동작되지 않도록 하기 위해서
if(isset($_POST) && $_SERVER['REQUEST_METHOD'] == "POST"){
@extract($_POST); // POST 전송으로 전달받은 값 처리
require_once 'phpclass/dbconnect.php';
require_once 'phpclass/loginClass.php';
$c = new LoginClass();
$column ="idx,userNM,mobileNO,telNO,photo";
$sql = "select idx,userNM,mobileNO,telNO,photo from Person";
if(!empty($search)) {
$where = "userNM LIKE '%".$search."%' or mobileNO LIKE '%".$search."%'";
} else {
$where = "";
}
if(strlen($where) > 0){
$sql .= " where ".$where;
}
$R = array(); // 결과 담을 변수 생성
$result = $c->putDbArray($sql);
while($row = $result->fetch_assoc()) {
if($row['photo'] == NULL) {
$row['photo'] = "";
} else {
$path = "./photos/".$row['photo'];
if(!file_exists($path)) {
$row['photo'] = "";
}
}
array_push($R, $row);
}
header("Cache-Control: no-cache, must-revalidate");
header("Content-type: application/json; charset=UTF-8");
echo json_encode(array('result'=>$R)); //배열-문자열등을 json형식의 '문자열'로 변환
}
?>
|
추가적으로 계속 유사 예제로 테스트하고 적어둘 예정이다.
'Flutter 앱 > Network' 카테고리의 다른 글
ListView.separated 예제 (0) | 2023.11.20 |
---|---|
Flutter Login Example (0) | 2022.07.25 |
Session vs JWT (0) | 2022.07.22 |
Flutter Login 로직 구현 예제 (오류 포함) (0) | 2022.07.22 |
Flutter DIO 라이브러리 예제2 (0) | 2022.07.02 |