inblog logo
|
Uni
    Flutter

    10. Flutter 수업- Android Studio로 shopapp 만들기(부분 리로딩)

    shopapp(부분 리로딩)
    홍윤's avatar
    홍윤
    Oct 02, 2024
    10. Flutter 수업- Android Studio로 shopapp 만들기(부분 리로딩)
    Contents
    위젯 트리에서 부분리로딩이 중요한 이유1. 전체 페이지 코드2. ★Header★(Context 분리, 부분 리로딩)3. _Circle()4. _field()

    위젯 트리에서 부분리로딩이 중요한 이유

    💡
    성능 최적화와 개발 효율성 때문에 위젯 트리에서 부분 리로딩이 중요한 이유이다.
    1. 성능 최적화: 위젯 트리 전체를 다시 렌더링하는 대신, 변경된 부분만 리로딩하면 불필요한 연산을 줄여 앱의 성능을 크게 향상시킬 수 있습니다. 이렇게 하면 사용자가 느끼는 UI 반응 속도가 빨라지고, 리소스를 절약할 수 있습니다.
    1. 개발 효율성: 부분 리로딩 덕분에 코드 수정 후 전체 앱을 다시 실행하지 않고, 수정된 부분만 빠르게 확인할 수 있습니다. 이는 개발 속도를 높이고, 실시간으로 변화를 테스트할 수 있게 해줍니다.
    따라서, 부분 리로딩은 성능과 개발 생산성을 모두 향상시키는 중요한 기능입니다.

    1. 전체 페이지 코드

    import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: ShopPage(), ); } } class ShopPage extends StatelessWidget { @override Widget build(BuildContext context) { print("ShopPage 그림 그려짐"); return Scaffold( appBar: AppBar(title: Text("쇼핑카트")), body: Column( children: [ // 1. 이미지, 이미지를 사용해서 사이즈를 맞추러면 AspectRatio 무조건 써야한다. Header(), // 2. 동그라미 두 개 _circle(), // 3. 텍스트 필드 (아이콘 포함) _field(), ], ), ); } //사람아이콘을 특정 위치에 넣고 싶을 때 Stack을 쓴다. Stack _field() { return Stack( children: [ TextFormField( maxLines: 3, decoration: InputDecoration( suffixIcon: Icon(Icons.person), enabledBorder: OutlineInputBorder(), ), ), Positioned( left: 200, top: 50, child: Icon(Icons.person), ), ], ); } // 동그란 두 개의 컨테이너를 보여주는 위젯 Container _circle() { return Container( width: 200, height: 200, decoration: BoxDecoration( color: Colors.white, // 바깥 컨테이너의 배경색 border: Border.all(), // 바깥 컨테이너의 테두리 borderRadius: BorderRadius.circular(100), ), child: Align( alignment: Alignment(1.0, 0.0), // -1.0~1.0(가로), -1.0~1.0(세로) child: Container( width: 150, height: 150, decoration: BoxDecoration( color: Colors.deepOrange, borderRadius: BorderRadius.circular(75),// 안쪽 컨테이너를 원형으로 만들기 위해 반지름을 75로 설정 ), ), ), ); } } class Header extends StatefulWidget { @override State<Header> createState() => _HeaderState(); } class _HeaderState extends State<Header> { // 객체의 상태! List<String> imageList = [ "https://picsum.photos/id/100/200/200", "https://picsum.photos/id/101/200/200" ]; // 상태 관리 int selectedIndex = 0; @override // build 실행하고 페이지를 다시 그리지 않게 하기 위해 Context를 분리해야 한다. // Context를 분리하려면 위젯을 하나 더 만들면 된다. // Context를 분리하면 부분 리로딩이 가능하다. Widget build(BuildContext context) { print("Header 그림 그려짐"); return Column( children: [ // AspectRatio를 사용해서 이미지를 비율에 맞춰 조절함 AspectRatio( aspectRatio: 3 / 2, child: Image.network( imageList[selectedIndex], fit: BoxFit.cover, ), ), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Container( width: 70, height: 70, decoration: BoxDecoration( color: Colors.grey, borderRadius: BorderRadius.circular(20), ), child: IconButton( onPressed: () { selectedIndex = 0; print("selectedIndex : $selectedIndex"); setState(() {}); }, icon: Icon(Icons.account_circle_sharp), ), ), Container( width: 70, height: 70, decoration: BoxDecoration( color: Colors.redAccent, borderRadius: BorderRadius.circular(20), ), child: IconButton( onPressed: () { selectedIndex = 1; print("selectedIndex : $selectedIndex"); setState(() {}); }, icon: Icon(Icons.access_alarms_sharp), ), ), ], ), ], ); } }

    2. ★Header★(Context 분리, 부분 리로딩)

    class ShopPage extends StatelessWidget { @override Widget build(BuildContext context) { print("ShopPage 그림 그려짐"); return Scaffold( appBar: AppBar(title: Text("쇼핑카트")), body: Column( children: [ // 1. 이미지, 이미지를 사용해서 사이즈를 맞추러면 AspectRatio 무조건 써야한다. Header(), //===================================================================== class Header extends StatefulWidget { @override State<Header> createState() => _HeaderState(); } class _HeaderState extends State<Header> { // 객체의 상태! List<String> imageList = [ "https://picsum.photos/id/100/200/200", "https://picsum.photos/id/101/200/200" ]; // 상태 관리 int selectedIndex = 0; @override // build 실행하고 페이지를 다시 그리지 않게 하기 위해 Context를 분리해야 한다. // Context를 분리하려면 위젯을 하나 더 만들면 된다. // Context를 분리하면 부분 리로딩이 가능하다. Widget build(BuildContext context) { print("Header 그림 그려짐"); return Column( children: [ // AspectRatio를 사용해서 이미지를 비율에 맞춰 조절함 AspectRatio( aspectRatio: 3 / 2, child: Image.network( imageList[selectedIndex], fit: BoxFit.cover, ), ), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Container( width: 70, height: 70, decoration: BoxDecoration( color: Colors.grey, borderRadius: BorderRadius.circular(20), ), child: IconButton( onPressed: () { selectedIndex = 0; print("selectedIndex : $selectedIndex"); setState(() {}); }, icon: Icon(Icons.account_circle_sharp), ), ), Container( width: 70, height: 70, decoration: BoxDecoration( color: Colors.redAccent, borderRadius: BorderRadius.circular(20), ), child: IconButton( onPressed: () { selectedIndex = 1; print("selectedIndex : $selectedIndex"); setState(() {}); }, icon: Icon(Icons.access_alarms_sharp), ), ), ], ), ], ); } }
    • 회색 아이콘을 클릭했을때 페이지 전체가 리로딩 되는 게 아니라 사진만 리로딩 된다.
    notion image
    notion image
    💡

    코드설명

    주요 개념 설명

    1. StatefulWidget과 setState

    • Header는 StatefulWidget을 상속받고 있으며, 이를 통해 화면의 상태를 동적으로 관리할 수 있습니다.
    • setState 메소드를 호출하면 상태가 변경되었음을 Flutter에 알리고, UI가 다시 렌더링됩니다.
    • 여기서는 selectedIndex가 변경될 때마다 UI를 다시 그려서 다른 이미지를 보여줍니다.

    2. imageList

    • imageList는 두 개의 이미지 URL을 담고 있는 리스트입니다. 이 리스트는 각각 다른 이미지를 나타내고, 선택된 인덱스에 따라 화면에 표시됩니다.
    • selectedIndex 값에 따라 imageList[selectedIndex]가 변경되고, AspectRatio 위젯에서 해당 이미지가 표시됩니다.

    3. AspectRatio

    • AspectRatio는 주어진 비율에 따라 위젯의 크기를 결정하는 데 사용됩니다. 여기서는 3:2 비율로 이미지를 표시하고 있습니다.
    • 이미지는 BoxFit.cover 속성을 사용하여 공간을 가득 채우도록 조정됩니다.

    4. 버튼 구성

    • 두 개의 버튼(IconButton)이 있고, 각각 다른 이미지를 선택하는 역할을 합니다.
    • 첫 번째 버튼을 누르면 selectedIndex가 0으로 설정되고, 두 번째 버튼을 누르면 selectedIndex가 1로 설정됩니다.
    • selectedIndex가 변경되면 setState()가 호출되어 화면이 다시 그려집니다.

    5. setState의 역할

    • setState()는 상태가 변경되었음을 알리고, Flutter가 이 변화를 감지하여 UI를 다시 그립니다.
    • 버튼을 클릭할 때마다 selectedIndex가 변경되고, 이에 맞춰 이미지가 변경됩니다.

    6. Container와 BoxDecoration

    • 버튼은 Container로 감싸져 있으며, BoxDecoration을 사용해 배경색과 둥근 모서리를 적용하고 있습니다.
    • 첫 번째 버튼은 회색, 두 번째 버튼은 빨간색(redAccent) 배경을 가지고 있으며, 각각 다른 아이콘을 표시합니다.

    동작 흐름

    1. 처음 화면에 selectedIndex 값이 0으로 설정되어 있어 첫 번째 이미지가 표시됩니다.
    1. 첫 번째 버튼을 클릭하면 selectedIndex가 0으로 변경되며 첫 번째 이미지가 계속 표시됩니다.
    1. 두 번째 버튼을 클릭하면 selectedIndex가 1로 변경되며, 두 번째 이미지로 변경됩니다.

    요약

    두 개의 버튼을 사용하여 화면에 표시되는 이미지를 동적으로 변경하는 코드입니다. 각 버튼은 클릭할 때 selectedIndex 값을 변경하고, 이에 따라 이미지가 바뀝니다. 이를 통해 상태 관리와 UI 업데이트 방법을 이해할 수 있습니다.

    3. _Circle()

    // 동그란 두 개의 컨테이너를 보여주는 위젯 Container _circle() { return Container( //바깥쪽 큰 원 width: 200, height: 200, decoration: BoxDecoration( color: Colors.white,// 바깥 컨테이너의 배경색 border: Border.all(),// 바깥 컨테이너의 테두리 borderRadius: BorderRadius.circular(100), ), child: Align( alignment: Alignment(1.0, 0.0), // -1.0~1.0(가로), -1.0~1.0(세로) child: Container( //안쪽 작은 원 width: 150, height: 150, decoration: BoxDecoration( color: Colors.deepOrange, borderRadius: BorderRadius.circular(75), ), ), ), ); } }
    notion image
    💡

    코드설명

    Align 위젯을 사용하여 작은 원 정렬
    • Align 위젯은 자식 위젯(작은 원)을 특정 위치에 배치할 수 있도록 합니다.
    • 여기서 alignment: Alignment(1.0, 0.0)는 작은 원을 바깥쪽 큰 원의 오른쪽 중앙에 배치하는 역할을 합니다.
      • Alignment(1.0, 0.0):
        • 1.0은 가로 방향에서 오른쪽 끝을 의미합니다.
        • 0.0은 세로 방향에서 중앙을 의미합니다.
        • 요약:

          두 개의 원형 컨테이너를 중첩하여 화면에 표시하는 코드입니다. 큰 원 안에 작은 원을 배치하고, 작은 원은 큰 원의 오른쪽 중앙에 배치됩니다. Align과 Container를 적절히 활용하여 원하는 위치에 원하는 모양의 컨테이너를 배치하는 방법을 보여줍니다.

    4. _field()

    //사람아이콘을 특정 위치에 넣고 싶을 때 Stack을 쓴다. Stack _field() { return Stack( children: [ TextFormField( maxLines: 3, decoration: InputDecoration( suffixIcon: Icon(Icons.person), enabledBorder: OutlineInputBorder(), ), ), Positioned( left: 200, top: 50, child: Icon(Icons.person), ), ], ); }
    notion image
    💡

    코드설명

    Stack의 주요 속성

    • Stack은 Flutter에서 여러 위젯을 겹쳐서 배치할 수 있는 위젯입니다.
    • children: Stack 안에 여러 자식 위젯을 배치할 수 있습니다.
    • alignment: 자식 위젯들의 기본 배치를 설정할 수 있습니다. 기본값은 좌상단입니다.
    • fit: Stack의 크기와 자식 위젯들의 크기를 조정할 때 사용됩니다.
    이 코드는 Stack을 사용하여 TextFormField 위에 아이콘을 원하는 위치에 정확히 배치하는 방법을 보여줍니다. Stack과 Positioned를 활용하면, 복잡한 레이아웃을 자유롭게 조정할 수 있습니다.

    Stack 위젯

    • Stack은 자식 위젯들을 겹치는 방식으로 배치합니다. 각 자식 위젯은 기본적으로 상하로 겹치며, 마지막에 추가된 자식이 위에 그려집니다. Positioned와 함께 사용하면, 자식 위젯을 특정 위치에 배치할 수 있습니다.
    • 사용 목적: Stack은 일반적으로 화면에 여러 요소를 겹치거나, 특정 요소를 배경에 고정하고 다른 요소를 그 위에 띄울 때 사용합니다.

    Positioned 위젯

    • *Positioned*는 Stack 내에서 사용되며, 자식 위젯을 특정 위치에 배치할 수 있습니다.
      • 예를 들어, 위의 코드에서는 left: 200과 top: 50을 통해 아이콘을 텍스트 필드의 위에 좌측에서 200, 상단에서 50 떨어진 위치에 정확히 배치합니다.
     
    Share article

    Uni

    RSS·Powered by Inblog