코딩하는 제리

[Flutter/Project](Instagram Clone) Firebase Storage Image Download 본문

Flutter/Project_InstaClone(완)

[Flutter/Project](Instagram Clone) Firebase Storage Image Download

JerryCho 2021. 2. 25. 17:05


post.dart -> 이미지 다운로드를 위한 변경점
이미지를 받아올 메서드 생성.


소스코드 및 pubspec.yaml

// repo/image_network_repository.dart

import 'dart:io';

import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_project_IJ/repo/helper/image_helper.dart';

// isolate
class ImageNetworkRepository {
  Future<void> uploadImageNCreateNewPost(File originImage,
      {@required String postKey}) async {
    try {
      // 메소드명만 입력.
      final File resized = await compute(getResizedImage, originImage);

      // postKey를 가져와 레퍼런스를 생성.
      final Reference reference =
          FirebaseStorage.instance.ref().child(_getImagePathByPostKey(postKey));

      // 파일 업로드.
      final UploadTask uploadTask = reference.putFile(resized);

      // uploadTask가 끝날 때까지 기다림.
      return await uploadTask;
    } catch (e) {
      print(e);
      return null;
    }
  }

  // postKey를 이용해 포스트 생성.
  String _getImagePathByPostKey(String postKey) => 'post/$postKey/post.jpg';

  // postKey를 이용해 해당 이미지를 받아옴.
  Future<dynamic> getPostImageUrl(String postKey) {
    return FirebaseStorage.instance
        .ref()
        .child(_getImagePathByPostKey(postKey))
        .getDownloadURL();
  }
}

ImageNetworkRepository imageNetworkRepository = ImageNetworkRepository();
// widgets/post.dart

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_project_IJ/constants/common_size.dart';
import 'package:flutter_project_IJ/constants/screen_size.dart';
import 'package:flutter_project_IJ/repo/image_network_repository.dart';
import 'package:flutter_project_IJ/widgets/comment.dart';
import 'package:flutter_project_IJ/widgets/rounded_avatar.dart';
import 'my_progress_indicator.dart';

class Post extends StatelessWidget {
  // final : 한번 데이터가 저장되면 바뀌지 않음.
  final int index;

  Post(
    this.index, {
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        _postHeader(),
        _postImage(),
        _postActionsButton(),
        _postLikes(),
        _postCaption()
      ],
    );
  }

  Padding _postCaption() {
    return Padding(
      padding: const EdgeInsets.symmetric(
        horizontal: common_gap, // 가로 양끝
        vertical: common_xxs_gap, // 세로 양끝.
      ),
      child: Comment(
        showImage: false,
        username: 'username123',
        text: 'Hello~~',
      ),
    );
  }

  Padding _postLikes() {
    return Padding(
      padding: const EdgeInsets.only(left: common_gap),
      child: Text(
        '12000 likes',
        style: TextStyle(fontWeight: FontWeight.bold),
      ),
    );
  }

  Row _postActionsButton() {
    return Row(
      children: <Widget>[
        IconButton(
          icon: ImageIcon(AssetImage('assets/images/bookmark.png')),
          onPressed: null,
          color: Colors.black87,
        ),
        IconButton(
          icon: ImageIcon(AssetImage('assets/images/comment.png')),
          onPressed: null,
          color: Colors.black87,
        ),
        IconButton(
          icon: ImageIcon(AssetImage('assets/images/direct_message.png')),
          onPressed: null,
          color: Colors.black87,
        ),
        Spacer(), // 위젯을 제외한 나머지 여백을 모두 차지
        IconButton(
          icon: ImageIcon(AssetImage('assets/images/heart.png')),
          onPressed: null,
          color: Colors.black87,
        ),
      ],
    );
  }

  Widget _postHeader() {
    return Row(
      children: [
        Padding(
          padding: const EdgeInsets.all(common_xxs_gap),
          child: RoundedAvatar(),
        ),
        Expanded(
          // 다른 위젯을 제외한 나머지 여백을 모두 차지
          child: Text("username"),
        ),
        IconButton(
          icon: Icon(
            Icons.more_horiz,
            color: Colors.black87,
          ),
          onPressed: null,
        ),
      ],
    );
  }

  Widget _postImage() {
    Widget progress = MyProgressIndicator(containerSize: size.width);
    return FutureBuilder<dynamic>(
        future: imageNetworkRepository
            .getPostImageUrl('1614223734395_wS3Hb5CAauMxNmFTi1IdQShhnwf2'),
        builder: (context, snapshot) {
          if (snapshot.hasData)
            return CachedNetworkImage(
              // CachedNetworkImage() 받아온 이미지를 캐시파일로 저장해 재사용.
              imageUrl: snapshot.data.toString(),
              placeholder: (BuildContext context, String url) {
                return progress;
              },
              imageBuilder:
                  (BuildContext context, ImageProvider imageProvider) {
                return AspectRatio(
                  aspectRatio: 1 / 1 /* 1대 1의 비율로 이미지 생성 */,
                  child: Container(
                    decoration: BoxDecoration(
                      image: DecorationImage(
                        image:
                            imageProvider /* CachedNetworkImage 의 imageUrl */,
                        fit: BoxFit.cover,
                      ),
                    ),
                  ),
                );
              },
            );
          else
            return progress;
        });
  }
}
Comments