[Flutter] http post를 주기적으로 보내보자 (1) 에러 잔치

Heeyoung Joe·2023년 11월 25일
0

Flutter

목록 보기
7/7

1 첫번째 에러

Unhandled Exception: Bad state: Cannot set the body fields of a Request with content-type "application/json".

이 에러는 body에 json이 아닌 내용이 들어간 것이라고 알려주는 exception이다.
jsonEncode()를 적용하지 않은 {"message" :"hi"}와 같은 딕셔너리를 바로 body에 아래와 같이 입력하면 이런게 나온다.

var response = Uri.post('http://127.0.0.1:8000', body : {"message" :"hi"},  headers: {"Content-Type": "application/json"});

2 두 번째 에러

Unhandled Exception: Converting object to an encodable object failed: Instance of 'DateTime'

이후에 class instance였던 futureGoal을 class method를 통해 json으로 변형한 것을 넣자 생긴 에러로 json이 지원하는 데이터타입에 DateTime이 포함되지 않기 때문에 생긴 에러였다. 아래와 같이 만들면 생긴다. DateTime 유형의 변수에 .toString()을 붙여서 toJson 함수를 고치면 된다.

models.dart


class Goal{
  int goal_id = 0;
  String? goal_text;
  int? user_id;
  DateTime? created_at;

  //constructor
  Goal(this.goal_text, this.user_id) 
  :
    goal_id = 1,
    created_at = DateTime.now()
    {
      print('Goal Generated : $goal_text from $goal_id');
    }
  
  Goal.createGoal(this.goal_text, this.user_id, this.goal_id)
  :
    created_at = DateTime.now()
    {
      goal_id = goal_id + 1; // 값을 변경하는 건 {} 안에서 하는 게 맞는 것 같다. 
      print('Goal Generated : $goal_text from $goal_id');
    }
  

  //json encode
  Map<String, dynamic> toJson() => {
    'goal_id': goal_id,
    'goal_text': goal_text,
    'user_id' : user_id,
    'created_at' : created_at
  };

}

backup.dart

import 'dart:convert';
import 'package:http_test/models.dart';
import 'package:http/http.dart' as http;

 Stream<int> setPost(int seconds) async* {
    yield* Stream.periodic(Duration(seconds: seconds), (int i) {
      backupGoal();
      return i;
    });
  }
//send http post about goal 
Future<int> backupGoal() async {

  // initialize goal 
  var goal = initGoal();

  //send post
  var url = Uri.parse("http://127.0.0.1:8000");
  var response;
  response = await http.post(url, body: jsonEncode(goal.toJson()), headers: {"Content-Type": "application/json"});

  return response.statusCode;
}


Goal initGoal(){
  // set content
  final goal_id = 2;
  final user_id = 0;
  final goal_text = "text";
  return Goal.createGoal(goal_text, user_id, goal_id);
}

3 세번째 에러

Unhandled Exception: ClientException with SocketException: Connection refused

이번 문제는 android emulater가 인지하는 localhost의 주소가 10.0.2.2이기 때문에 발생했다. 127.0.0.1을 10.0.2.2로 대체해주고 Django의 settings.py에 ALLOWED_HOSTS = ['10.0.2.2'] 를 넣어주면 된다.

성공!

다음 과제

  1. duration을 추가하여 10초에 한 번씩 수행하도록 하기
  2. 로컬에 class instance를 저장하고 불러오기
  3. 불러온 데이터를 http request를 통해 django로 보내주기
profile
SW Engineer

0개의 댓글