반응형
    
    
    
  1. S3에 이미지를 올린다.
https://devboi.tistory.com/564 참고하여, S3 구성

테스트 이미지 세팅
2.플러터 S3이미지 호출 방법
assets가 아닌 외부 Url로 이미지를 세팅하는 방법은 이렇다.
Image.network(
              "s3주소/image/3126993.png",
              height: 170,
              width: MediaQuery.of(context).size.width,
              fit: BoxFit.cover,
            ),
3. 확인

4. 데모 백엔드 서버 구성
Docker-compose + Spring Hibernate + Mariadb (비즈니스 로직에 따라 querydsl 옵셔널)

5. 플러터에서 데모 백엔드 호출
라이브러리 추가 + http 통신 api 개발
http: ^0.13.5Future<List<PostItem>> getApiGet(Map<String, dynamic>? param) async{
  print('get Api get 호출');
  Iterable l;
  late List<PostItem> posts ;
  var url = Uri.http(backendHost, 'content',param);
  var response = await http.get(url).then((value) =>
  {
        l = json.decode(value.body),
       posts = List<PostItem>.from(l.map((model)=> PostItem.fromJson(model)))
  }
  );
  return  posts;
}api를 호출하는 Widget 소스이다
class _HomeState extends State<Home> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Feeds"),
        centerTitle: true,
        actions: <Widget>[
          IconButton(
            icon: Icon(
              Icons.filter_list,
            ),
            onPressed: () {},
          ),
        ],
      ),
      body: Container(
        child: FutureBuilder(
          future: getApiGet({'asfa':'asfas'}),
          builder: (context,AsyncSnapshot snapshot){
          if (snapshot.hasData) {
            print(snapshot);
            return ListView.builder(
              padding: EdgeInsets.symmetric(horizontal: 20),
              itemCount: snapshot.data.length,
              itemBuilder: (BuildContext context, int index) {
                PostItem item = snapshot.data[index];
                return PostItem(dp: item.dp,name: item.name,img: item.img,time: item.time,);
              },
            );
          }
          else
            {
              return Container(
                child: Center(
                  child: Text("Loading..."),
                ),
              );
            }
          }
        )
      ),class PostItem extends StatefulWidget {
  var dp;
  var name;
  var time;
  var img;
  PostItem({
    super.key,
    required this.dp,
    required this.name,
    required this.time,
    required this.img,
  });
  factory PostItem.fromJson(dynamic? json){
    PostItem item =  PostItem(dp: json?['dp'],name: json?['name'],time: json?['time'],img: json?['img']);
    return item;
  }
  @override
  _PostItemState createState() => _PostItemState();
}
class _PostItemState extends State<PostItem> {위는 게시글에 대한 모델 소스이다.
리스트 뷰에 부를때는 FutureBuilder를 사용한다. 그러면 초기화에 대한 이슈가 자동으로 해결된다.

이렇게 목록들이 리스트 뷰로 그려준다.
전체 소스는 이렇다.
import 'package:flutter/material.dart';
class PostItem extends StatefulWidget {
  var dp;
  var name;
  var time;
  var img;
  PostItem({
    super.key,
    required this.dp,
    required this.name,
    required this.time,
    required this.img,
  });
  factory PostItem.fromJson(dynamic? json){
    PostItem item =  PostItem(dp: json?['dp'],name: json?['name'],time: json?['time'],img: json?['img']);
    return item;
  }
  @override
  _PostItemState createState() => _PostItemState();
}
class _PostItemState extends State<PostItem> {
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.symmetric(vertical: 5),
      child: InkWell(
        child: Column(
          children: <Widget>[
            ListTile(
              leading: CircleAvatar(
                backgroundImage: AssetImage(
                  "${widget.dp}",
                ),
              ),
              contentPadding: EdgeInsets.all(0),
              title: Text(
                "${widget.name}",
                style: TextStyle(
                  fontWeight: FontWeight.bold,
                ),
              ),
              trailing: Text(
                "${widget.time}",
                style: TextStyle(
                  fontWeight: FontWeight.w300,
                  fontSize: 11,
                ),
              ),
            ),
            Image.network(
              "https://gshotbucket.s3.ap-northeast-2.amazonaws.com/image/3126993.png",
              height: 170,
              width: MediaQuery.of(context).size.width,
              fit: BoxFit.cover,
            ),
          ],
        ),
        onTap: () {},
      ),
    );
  }
}import 'dart:convert';
import 'package:boilerflutterapp/view/widget/post/post_item.dart';
import 'package:http/http.dart' as http;
const String backendHost = "localhost:8080";
const String imageS3Host = "https://gshotbucket.s3.ap-northeast-2.amazonaws.com/image";
Future<List<PostItem>> getApiGet(Map<String, dynamic>? param) async{
  Iterable l;
  late List<PostItem> posts ;
  var url = Uri.http(backendHost, 'content',param);
  await http.get(url).then((value) =>
  {
        l = json.decode(value.body),
       posts = List<PostItem>.from(l.map((model)=> PostItem.fromJson(model)))
  }
  );
  return  posts;
}import 'package:boilerflutterapp/http/httpApi.dart';
import 'package:flutter/material.dart';
import '../../widget/post/post_item.dart';
class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Feeds"),
        centerTitle: true,
        actions: <Widget>[
          IconButton(
            icon: Icon(
              Icons.filter_list,
            ),
            onPressed: () {},
          ),
        ],
      ),
      body: Container(
        child: FutureBuilder(
          future: getApiGet({'asfa':'asfas'}),
          builder: (context,AsyncSnapshot snapshot){
          if (snapshot.hasData) {
            print(snapshot);
            return ListView.builder(
              padding: EdgeInsets.symmetric(horizontal: 20),
              itemCount: snapshot.data.length,
              itemBuilder: (BuildContext context, int index) {
                PostItem item = snapshot.data[index];
                return PostItem(dp: item.dp,name: item.name,img: item.img,time: item.time,);
              },
            );
          }
          else
            {
              return Container(
                child: Center(
                  child: Text("Loading..."),
                ),
              );
            }
          }
        )
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(
          Icons.add,
          color: Colors.white,
        ),
        onPressed: () {},
      ),
    );
  }
}이러면 무한으로 Listview Builder가 무한 리스트뷰를 그려준다.
반응형
    
    
    
  '[Mobile] > [Flutter]' 카테고리의 다른 글
| [Flutter] Search Module (2) | 2023.08.20 | 
|---|---|
| [Flutter] 친구 레이아웃 끝내기 (1) | 2023.08.19 | 
| [Flutter] BoilerTemplate 리스트 뷰 개념 (0) | 2023.08.12 | 
| [Flutter] Splash Screen 에서 로그인 정보 기반 핸들링(자동로그인) (0) | 2023.08.12 | 
| [Flutter] 플러터 다트 버전 업 및 다트 버전 관리 (0) | 2023.08.11 | 
 
                  
                 
                  
                