본문 바로가기
Application/Flutter

[Cookbook] Networking - 데이터 삭제

by 비나래 2022. 7. 20.

요약

http package를 이용해서 data 삭제

 

전체 과정

1. http Package 추가

2. Server에서의 data 삭제

3. Screen 업데이트

 

상세 과정

1. http Package 추가

- pubspec.yaml 파일의 dependency 에 http 추가

- import 'package:http/http.dart' as http;

 

2. http.delete() method

- http.delete() method는 Response를 포함하고 있는 Future를 반환

- Future는 async 동작에 사용되는 중요한 클래스 (Potential 값 및 error를 저장할 수 있는 객체)

- Future<http.response> / Uri.parse를 통해서, URL을 입력 / header도 별도로 추가해주기

Future<http.Response> deleteAlbum(String id) async {
  final http.Response response = await http.delete(
    Uri.parse('http://jsonplaceholder.typicode.com/albums/$id'),
    headers: <String, String> {
      'Content-Type': 'application/json; charset=UTF-8',
    },
  );
  return response;
}


3. update the screen

- data를 삭제한 후에 setState를 통해서 상태를 업데이트 해줌

- 이 예제의 경우 화면에 표시된 id를 활용하는 경우가 있는데, snapshot을 활용

Column(
	mainAxisAlignment: MainAxisAlignment.center,
    children: <Widget>[
        // snapshot.data?.title ?? 'Deleted' : null이면 'Deleted'를 입력하라.
        // snapshot : JSON 형태의 Object를 쉽게 접근할 수 있도록 해주는 library
    	Text(snapshot.data?.title ?? 'Deleted'),
        ElevatedButton(
        	child: const Text('Delete Data'),
            onPressed: () {
            	setState(() {
                	_futureAlbum =
                    	deleteAlbum(snapshot.data!.id.toString());
                });
            },
        ),
   ]
);

 

4. Returning a response

- Album.fromJson(jsonDecode(response.body));

- if (response.stautsCode == 200)

- throw Exception('Failed to delete album')

Future<Album> deleteAlbum(String id) async {
  final http.Response response = await http.delete(
    Uri.parse('https://jsonplaceholder.typicode.com/albums/$id'),
    headers: <String, String>{
      'Content-Type': 'application/json; charset=UTF-8',
    },
  );

  if (response.statusCode == 200) {
    return Album.fromJson(jsonDecode(response.body));
  } else {
    throw Exception('Failed to delete album.');
  }
}

 

[Complete Example]

- CircularProgressIndicator();

- factory Album.fromJson(Map<String, dynamic> json)

 

import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() => runApp(const MyApp());

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

  @override
  // in case of StatefulWidget
  // 'createState()' Method needs to be override.
  State<MyApp> createState() {
    return _MyAppState();
  }
}

class _MyAppState extends State<MyApp> {
  late Future<Album> _futureAlbum;

  @override
  void initState() {
    super.initState();
    _futureAlbum = fetchAlbum();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Deleting Data Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Delete Data Example'),
        ),
        body: Center(
          child: FutureBuilder<Album>(
            future: _futureAlbum,
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                if (snapshot.hasData) {
                  return Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      Text(snapshot.data?.title ?? "Deleted"),
                      ElevatedButton(
                        child: const Text('Delete Data'),
                        onPressed: () {
                          setState(() {
                            _futureAlbum =
                                deleteAlbum(snapshot.data!.id.toString());
                          });
                        },
                      ),
                    ],
                  );
                } else if (snapshot.hasError) {
                  return Text('${snapshot.error}');
                }
              }
              return const CircularProgressIndicator();
            }
          ),
        ),
      ),
    );
  }
}

class Album {
    final int? id;
    final String? title;

    const Album({this.id, this.title});

    factory Album.fromJson(Map<String, dynamic> json) {
      return Album(
        id: json['id'],
        title: json['title'],
      );
    }
}

Future<Album> fetchAlbum() async {
    final response = await http.get(
      Uri.parse('https://jsonplaceholder.typicode.com/albums/1'),
    );

    if (response.statusCode == 200) {
      return Album.fromJson(jsonDecode(response.body));
    } else {
      throw Exception('Failed to load album');
    }
}

Future<Album> deleteAlbum(String id) async {
  final http.Response response = await http.delete(
    Uri.parse('https://jsonplaceholder.typicode.com/albums/$id'),
    headers: <String, String> {
      'Content-Type': 'application/json; charset=UTF-8',
    },
  );

  if (response.statusCode == 200) {
    return Album.fromJson(jsonDecode(response.body));
  } else {
    throw Exception('Failed to delete album.');
  }
}

 

All the contents comes from the official Flutter Document (cookbook)

https://docs.flutter.dev/cookbook/networking/delete-data