Flutter

[Flutter] 앱이 서버와 데이터 주고받는 법

hminor 2023. 8. 9. 16:34

앱이 서버와 데이터 주고받는 법

  • Flutter에서 GET, POST 요청을 하는 방법
    • pubspec.yaml의 dependencies에 아래 코드 추가 후 Pub get 클릭해서 설치하기
dependencies:
  flutter:
    sdk: flutter
  http: ^0.13.4
  • 이후 android/app/src/main/AndroidManifest.xml 파일에 코드 삽입
    • 해당 코드는 인터넷 사용 허락에 대한 코드
    • 안드로이드만 설치가 필요하고 IOS는 별도 설치가 필요하지 않다고 함
     <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.instagram"
        >
    
        <uses-permission android:name="android.permission.INTERNET" />
  • 마지막으로 main.dart 파일의 상단에 import 해오기
import 'package:http/http.dart' as http;
import 'dart:convert';
  • 이제 요청을 해볼 텐데
    • 앱이 로드 되었을 경우 바로 요청을 해 데이터를 뿌리기 위해 initState() 위젯을 사용하기
    • 여기서 get 요청을 하는 코드는 아래와 같다.
      • http.get(Uri.parse('API주소'));
    • 요청한 데이터는 변수에 담아 변수.body를 해야 볼 수 있다.
    • 다만 함수 실행 보다 출력 또는 처리하는 로직이 더 빠르기에 비동기 통신으로 async, await을 처리하려고 하지만
    • initState는 async, await 처리를 할 수 없다.
    • 그래서 initState() 밖에 비동기 통신 함수를 작성 후 안에 추가하게 되면 의도대로 실행 됨.
	getData() async{
    var result = await http.get(Uri.parse('경로'));
    print(result.body);
  }

  @override
  void initState() {
    super.initState();
    getData();
  }
  • 그런데 받아온 데이터는 JSON 자료형이기에 jsonDecode를 사용해 사용할 수 있게 변형해주기
    • jsonDecode(result.body)

 

숙제

경로로 부터 받아온 데이터를 뿌리고 빈 배열로 생기는 에러 또한 함께 처리하기

  • 에러 해결의 경우엔 현재 homeData의 개수에 맞게 출력을 하도록 하니 잘 해결 되었다.
import 'package:flutter/material.dart';
import './style.dart' as style;
import 'package:http/http.dart' as http;
import 'dart:convert';

void main() {
  runApp(
    MaterialApp(
      theme: style.theme,
      home: MyApp()
    )
  );
}

class MyApp extends StatefulWidget {
  MyApp({super.key});
  
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  var homeData = [];

  getData() async{
    var result = await http.get(Uri.parse('경로'));
    setState(() {
      homeData = jsonDecode(result.body);
    });
  }

  @override
  void initState() {
    super.initState();
    getData();
  }

  // 0: home, 1: shop
  var tab = 0;

  changeTab(tabNumber){
    setState(() {
      tab = tabNumber;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Instagram'),
          actions: [
            IconButton(
              onPressed: (){},
              icon: Icon(Icons.add_box_outlined)
            )
          ],
        ),
      body: [Home(homeData:homeData),Text('shop')][tab],
      bottomNavigationBar: BottomNavigationBar(
        onTap: (i){
          changeTab(i);
        },
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.home_outlined),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.shopping_bag_outlined),
            label: 'Shopping',
          ),
        ],
        showSelectedLabels: false, // 선택된 아이템의 레이블 숨김
        showUnselectedLabels: false, // 선택되지 않은 아이템의 레이블 숨김
      ),
    );
  }
}

class Home extends StatelessWidget {
  Home({super.key, this.homeData});
  final homeData;
  @override
  Widget build(BuildContext context) {
    return ListView.builder(
        itemCount: homeData.length,
        itemBuilder: (context, idx){
          return Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Image.network(homeData[idx]['image']),
              Container(
                margin: EdgeInsets.fromLTRB(10, 20, 10, 20),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Row(
                      children: [
                        Text('좋아요', style: TextStyle(fontSize: 15, fontWeight: FontWeight.w700),),
                        Text(homeData[idx]['likes'].toString(), style: TextStyle(fontSize: 15, fontWeight: FontWeight.w700)),
                      ],
                    ),
                    Text(homeData[idx]['date'].toString()),
                    Text(homeData[idx]['content'].toString()),
                  ],
                ),
              )
            ],
          );
        },
    );
  }
}