카테고리 없음

6주차 주간과제

신승호. 2023. 3. 5. 23:19
  1. 아래는 공개된 API의 리스트를 공유하는 Github 문서이다. 아래의 링크에 들어가서, 공개되어있는 API중 하나를 분석하고 직접 기획하여 본인이 기획한 어플을 제작하시오.
  2. 기획 과제내용을 간단히 2-3줄로 설명하여 제출하시오. 이 때 해결 과정을 함께 포함하여 정리하시오. (어려웠던 내용과 헤맸던 내용이 있다면 반드시 기재할 것)
  3. 다음의 조건을 반드시 만족할 것.
    • 페이지는 두 페이지 이상이어야 하며 네비게이션을 활용하여 페이지 이동이 포함될 것
    • 클래스를 작성하여 Serialization이 적용될 수 있도록 할 것
    • 적절한 애니메이션 효과를 포함할 것

 

API를 고르는데 뭐가 뭔지 모르겠고.. 그래도 스포츠앱을 만들어 보고 싶어서 찾아봤는데 키가 있어야하고.. 해리포터 API가 JSON이 쉽게 바로 나와서 해리포터 API를 골랐다.

all characters:    전체 등장인물
https://hp-api.onrender.com/api/characters

characters who are Hogwarts students during the book series:  호그와트 학생
https://hp-api.onrender.com/api/characters/students

characters who are Hogwarts staff during the book series: 호그와트 직원
https://hp-api.onrender.com/api/characters/staff

characters in a certain house, e.g. /gryffindor:  등장인물 기숙사
https://hp-api.onrender.com/api/characters/house/:house

all spells:  마법주문
https://hp-api.onrender.com/api/spells

이런 예제도 나와있어서 비슷하게 만들어보고싶다.

 

아직 이해를 못했나봅니다 제가..

import 'package:harrypoter_app/model/wand.dart';

class Character {
  String id;
  String name;
  List<String>? alternate_names;
  String species;
  String gender;
  String? house;
  DateTime? dateOfBirth;
  String? yearOfBirth;
  bool wizard;
  String? ancestry;
  String? eyeColour;
  String hairColour;
  Wand wand;
  String? patronus;
  bool hogwartsStudent;
  bool hogwartsStaff;
  String? actor;
  List<String>? alternate_actors;
  bool alive;
  String? image;

  Character({
    required this.id,
    required this.name,
    required this.alternate_names,
    required this.species,
    required this.gender,
    required this.house,
    required this.dateOfBirth,
    required this.yearOfBirth,
    required this.wizard,
    required this.ancestry,
    required this.eyeColour,
    required this.hairColour,
    required this.wand,
    required this.patronus,
    required this.hogwartsStudent,
    required this.hogwartsStaff,
    required this.actor,
    required this.alternate_actors,
    required this.alive,
    required this.image,
  });

  factory Character.fromMap(Map<String, dynamic> map) {
    return Character(
        id: map['id'],
        name: map['name'],
        alternate_names: map['alternate_names'] != null
            ? List<String>.from(map['alternate_names'])
            : null,
        species: map['species'],
        gender: map['gender'],
        house: map['house'],
        dateOfBirth: map['dateOfBirth'],
        yearOfBirth: map['yearOfBirth'],
        wizard: map['wizard'],
        ancestry: map['ancestry'],
        eyeColour: map['eyeColour'],
        hairColour: map['hairColour'],
        wand: Wand.fromMap(map['wand']) ,
        patronus: map['patronus'],
        hogwartsStudent: map['hogwartsStudent'],
        hogwartsStaff: map['hogwartsStaff'],
        actor: map['actor'],
        alternate_actors: map['alternate_names'] != null
            ? List<String>.from(map['alternate_actors'])
            : null,
        alive: map['alive'],
        image: map['image']);
  }
}

등장인물 JSON에 있는 타입은 다 넣었고 null일 수도 있는것들을 nullsafety처리

 

lib/model/wand.dart

class Wand {
  String? wood;
  String? core;
  int? length;

  Wand({required this.wood, required this.core, required this.length});

  factory Wand.fromMap(Map<String, dynamic> map) {
    return Wand(wood: map['wood'], core: map['core'], length: map['length']);
  }
}

main.dart

import 'package:flutter/material.dart';
import 'package:harrypoter_app/page/mainpage.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark(),
      home: MainPage(),
    );
  }
}

 

lib/page/mainpage.dart

여기부터 테스트하면서 해보려고 일단 대충만들어놓음

import 'package:flutter/material.dart';
import 'package:harrypoter_app/page/spellpage.dart';
import 'package:harrypoter_app/page/staffpage.dart';
import 'package:harrypoter_app/page/studentpage.dart';

class MainPage extends StatefulWidget {
  const MainPage({super.key});

  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        alignment: Alignment.center,
        decoration: BoxDecoration(
            image: DecorationImage(
                fit: BoxFit.cover,
                colorFilter: ColorFilter.mode(Colors.black38, BlendMode.darken),
                image: NetworkImage(
                    'https://images.christiandaily.co.kr/data/images/full/68175/image.jpg?w=600'))),
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ListTile(
                onTap: () {
                  Navigator.push(context,
                      MaterialPageRoute(builder: ((context) {
                    return StudentPage();
                  })));
                },
                tileColor: Colors.white,
                title: Text('호그와트 학생'),
                subtitle: Text('명단보기'),
              ),
              ListTile(
                onTap: () {
                  Navigator.push(context,
                      MaterialPageRoute(builder: ((context) {
                    return StaffPage();
                  })));
                },
                tileColor: Colors.white,
                title: Text('호그와트 직원'),
                subtitle: Text('명단보기'),
              ),
              ListTile(
                onTap: () {
                  Navigator.push(context,
                      MaterialPageRoute(builder: ((context) {
                    return SpellPage();
                  })));
                },
                tileColor: Colors.white,
                title: Text('호그와트 마법주문'),
                subtitle: Text('윙가르디움 레비오사~'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

MainPage

spell.dart

class Spell {
  String id;
  String name;
  String descriprion;

  Spell({required this.id, required this.name, required this.descriprion});

  factory Spell.fromMap(Map<String, dynamic> map) {
    return Spell(
        id: map['id'], name: map['name'], descriprion: map['descriprion']);
  }
}

SpellPage.dart

// ignore_for_file: prefer_const_constructors

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:harrypoter_app/model/spell.dart';

class SpellPage extends StatefulWidget {
  const SpellPage({super.key});

  @override
  State<SpellPage> createState() => _SpellPageState();
}

class _SpellPageState extends State<SpellPage> {
  List<Spell> spell = [];
  Dio dio = Dio();

  var url = 'https://hp-api.onrender.com/api/spells';

  readData() async {
    var res = await dio.get(url);
    if (res.statusCode == 200) {
      var magic = List<Map<String, dynamic>>.from(res.data);
      setState(() => spell = magic.map((e) => Spell.fromMap(e)).toList());
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          centerTitle: true,
          backgroundColor: Colors.transparent,
          elevation: 0,
          title: Text(
            'Spell',
            style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),
          ),
        ),
        body: ListView.builder(
            itemCount: spell.length,
            itemBuilder: ((context, index) {
              return ListTile(
                title: Text(spell[index].name),
                subtitle: Text(spell[index].descriprion),
              );
            })));
  }
}

일단 SpellPage부터 막혔다. ListTile형태로 스크롤하면서 내리려고 했는데..

아무것도 뜨지않음;

StaffPage.dart

// ignore_for_file: prefer_const_constructors

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:harrypoter_app/model/character.dart';

class StaffPage extends StatefulWidget {
  const StaffPage({super.key});

  @override
  State<StaffPage> createState() => _StaffPageState();
}

class _StaffPageState extends State<StaffPage> {
  List<Character> staffs = [];
  Dio dio = Dio();
  var url = 'https://hp-api.onrender.com/api/characters/staff';

  readData() async {
    var res = await dio.get(url);
    if (res.statusCode == 200) {
      var staff = List<Map<String, dynamic>>.from(res.data);
      setState(() => staffs = staff.map((e) => Character.fromMap(e)).toList());
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: Text(
          'Staff',
          style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),
        ),
        backgroundColor: Colors.transparent,
        elevation: 0,
      ),
      body: Container(
          alignment: Alignment.center,
          decoration: BoxDecoration(
              image: DecorationImage(
                  fit: BoxFit.cover,
                  colorFilter:
                      ColorFilter.mode(Colors.black38, BlendMode.darken),
                  image: NetworkImage(
                      'https://mblogthumb-phinf.pstatic.net/20110728_125/eponine77_1311816657845yd7Co_JPEG/67900_S45_130538.jpg?type=w2'))),
          child: PageView.builder(
              itemCount: staffs.length,
              itemBuilder: ((context, index) {
                return Center(child: Image.network(staffs[index].image!));
              }))),
    );
  }
}

lib/page/studentpage.dart

// ignore_for_file: prefer_const_constructors

import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';

class StudentPage extends StatefulWidget {
  const StudentPage({super.key});

  @override
  State<StudentPage> createState() => _StudentPageState();
}

class _StudentPageState extends State<StudentPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text('학생페이지'),
      ),
    );
  }
}

dio부분 강의를 다시 들어보겠습니다..

 

class부분은 맞는지 알고싶습니다.