Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android studio 如果提供了ParseConnectivityProvider,则LiveQuery不起作用_Android Studio_Flutter_Dart_Parse Server - Fatal编程技术网

Android studio 如果提供了ParseConnectivityProvider,则LiveQuery不起作用

Android studio 如果提供了ParseConnectivityProvider,则LiveQuery不起作用,android-studio,flutter,dart,parse-server,Android Studio,Flutter,Dart,Parse Server,我正在开发一个颤振应用程序,它由一个具有解析服务器背景的员工调度器组成。该应用程序的工作原理如下: 1) 用户打开应用程序 2) 该应用程序显示可用员工的卡片列表(如果服务器数据库中有) 3) 用户可以编辑、确认或删除员工可用性 应用程序正在运行。这意味着我也可以从解析服务器和应用程序屏幕中对数据进行CRUD 目标:数据库中的每次数据更改都需要刷新(实时)用户屏幕,删除或更新(更改的)数据本身 我的想法:使用parse_server_sdk:^2.0.1作为依赖项(pubspec.yaml)并实

我正在开发一个颤振应用程序,它由一个具有解析服务器背景的员工调度器组成。该应用程序的工作原理如下:

1) 用户打开应用程序
2) 该应用程序显示可用员工的卡片列表(如果服务器数据库中有)
3) 用户可以编辑、确认或删除员工可用性

应用程序正在运行。这意味着我也可以从解析服务器和应用程序屏幕中对数据进行CRUD

目标:数据库中的每次数据更改都需要刷新(实时)用户屏幕,删除或更新(更改的)数据本身

我的想法:使用parse_server_sdk:^2.0.1作为依赖项(pubspec.yaml)并实现实时查询(作为github文档)

问题:编译后,尽管我的AndroidStudio从视觉上讲不会崩溃,我的应用程序本身也不会崩溃,但它向我(日志)显示“如果提供了ParseConnectionProvider,LiveQuery将无法工作”

没有问题(main.dart):

造成问题的原因:

void main() async{

//the following parameters are in other file (constants.dart)...they are working

  Parse().initialize(
    kParseApplicationId,
    kParseServerUrl,
    masterKey: kParseMasterKey,
    clientKey: kParseClientKey,
    debug: true,
    liveQueryUrl: kLiveQueryUrl,
    autoSendSessionId: true,
  );

  var dietPlan = ParseObject('DietPlan')
    ..set('Name', 'Ketogenic')
    ..set('Fat', 65);
  await dietPlan.save();

  var response = await dietPlan.save();
  if (response.success) {
    dietPlan = response.result;
  }

  //until here, the program works well.The data is inserted and retrieved, ok...but exactly here..the problem!

  final LiveQuery liveQuery = LiveQuery(); //from here..this is causing problems

  QueryBuilder<ParseObject> query =
  QueryBuilder<ParseObject>(ParseObject('DietPlan'))
    ..whereEqualTo('intNumber', 1);

  Subscription subscription = await liveQuery.client.subscribe(query);

  subscription.on(LiveQueryEvent.delete, (value) {
    print('*** DELETE ***: ${DateTime.now().toString()}\n $value ');
    print((value as ParseObject).objectId);
    print((value as ParseObject).updatedAt);
    print((value as ParseObject).createdAt);
    print((value as ParseObject).get('objectId'));
    print((value as ParseObject).get('updatedAt'));
    print((value as ParseObject).get('createdAt'));
  });

  runApp(MyApp());
}
有人能帮我解决这个问题吗?提前谢谢

在下面,我将显示我的所有代码(main.dart):

//版权所有2018颤振团队。版权所有。
//此源代码的使用受BSD样式许可证的约束,该许可证可以
//在许可证文件中找到。
导入“dart:convert”;
进口“包装:颤振/cupertino.dart”;
进口“包装:颤振/材料.省道”;
导入“package:flatter_datetime_picker/flatter_datetime_picker.dart”;
导入“包:intl/intl.dart”;
导入“package:flatter_本地化/flatter_本地化.dart”;
导入“package:marca_horario/model/data.dart”;
导入“包:marca_horario/network_utils/data_utils.dart”;
导入“包:http/http.dart”;
导入“package:parse_server_sdk/parse_server_sdk.dart”;
导入“package:marca_horario/constants.dart”;
void myLQ()异步{
Parse().initialize(
kParseApplicationId,
kParseServerUrl,
万能钥匙:kParseMasterKey,
clientKey:kParseClientKey,
是的,
liveQueryUrl:kLiveQueryUrl,
autoSendSessionId:对,
);
var dietPlan=ParseObject('dietPlan')
..集合('名称','生酮')
..套('Fat',65);
等待计划。保存();
var response=wait dietPlan.save();
if(response.success){
dietPlan=响应。结果;
}
final LiveQuery LiveQuery=LiveQuery();
QueryBuilder查询=
QueryBuilder(ParseObject('DietPlan'))
..其中Equalto('intNumber',1);
订阅订阅=等待liveQuery.client.subscribe(查询);
subscription.on(LiveQueryEvent.delete,(value){
打印('***删除***:${DateTime.now().toString()}\n$value');
打印((值作为ParseObject.objectId);
打印((值为ParseObject).updatedAt);
打印((值为ParseObject).createdAt);
print((值为ParseObject.get('objectId'));
print((值作为ParseObject.get('updatedAt'));
print((值作为ParseObject.get('createdAt'));
});
}
void main()异步{
Parse().initialize(
kParseApplicationId,
kParseServerUrl,
万能钥匙:kParseMasterKey,
clientKey:kParseClientKey,
是的,
liveQueryUrl:kLiveQueryUrl,
autoSendSessionId:对,
);
var dietPlan=ParseObject('dietPlan')
..集合('名称','生酮')
..套('Fat',65);
等待计划。保存();
var response=wait dietPlan.save();
if(response.success){
dietPlan=响应。结果;
}
final LiveQuery LiveQuery=LiveQuery();
QueryBuilder查询=
QueryBuilder(ParseObject('DietPlan'))
..其中Equalto('intNumber',1);
订阅订阅=等待liveQuery.client.subscribe(查询);
subscription.on(LiveQueryEvent.delete,(value){
打印('***删除***:${DateTime.now().toString()}\n$value');
打印((值作为ParseObject.objectId);
打印((值为ParseObject).updatedAt);
打印((值为ParseObject).createdAt);
print((值为ParseObject.get('objectId'));
print((值作为ParseObject.get('updatedAt'));
print((值作为ParseObject.get('createdAt'));
});
runApp(MyApp());
}
类MyApp扩展了StatefulWidget{
@凌驾
_MyAppState createState()=>\u MyAppState();
}
类MyAppState扩展了状态{
@凌驾
小部件构建(构建上下文){
返回材料PP(
本地化授权:[
GlobalMaterialAllocalizations.delegate,
GlobalWidgetsLocalizations.delegate
],
supportedLocales:[const Locale('pt','BR')],
home:home()
);
}
}
类Home扩展了StatefulWidget{
@凌驾
_HomeState createState()=>\u HomeState();
}
类(HomeState扩展状态){
var_listiles=List();
颜色_iconColor=Colors.black;
颜色标准颜色=Colors.black;
颜色替换颜色=Colors.green;
TextEditingController _nameController=TextEditingController();
var_scaffoldKey=new GlobalKey();
字符串standardTileTitle=“Adicione um horário disponível…”;
String_titleTile=“Adicione um horário disponível…”;
字符串_tileSubtitle=“Edite o nome do functionário…”;
int _selectedIndexBottomNavBar=0;
最终GlobalKey _refreshIndicatorKey=新GlobalKey();
@凌驾
小部件构建(构建上下文){
返回刷新指示器(
键:_refreshIndicatorKey,
onRefresh:()异步{
设置状态(){
});},
孩子:脚手架(
钥匙:_scaffoldKey,
浮动操作按钮:浮动操作按钮(
已按下:(){
invokeDatePicker();
},
子:图标(Icons.add),
),
bottomNavigationBar:bottomNavigationBar(),
appBar:appBar(
标题:文本(“Marca Horário”),
),
//正文:中(
//child:Text('Hello World'),
正文:bodyStartScreen()
),
);
}
小部件底部导航栏(){
无效
void main() async{

//the following parameters are in other file (constants.dart)...they are working

  Parse().initialize(
    kParseApplicationId,
    kParseServerUrl,
    masterKey: kParseMasterKey,
    clientKey: kParseClientKey,
    debug: true,
    liveQueryUrl: kLiveQueryUrl,
    autoSendSessionId: true,
  );

  var dietPlan = ParseObject('DietPlan')
    ..set('Name', 'Ketogenic')
    ..set('Fat', 65);
  await dietPlan.save();

  var response = await dietPlan.save();
  if (response.success) {
    dietPlan = response.result;
  }

  //until here, the program works well.The data is inserted and retrieved, ok...but exactly here..the problem!

  final LiveQuery liveQuery = LiveQuery(); //from here..this is causing problems

  QueryBuilder<ParseObject> query =
  QueryBuilder<ParseObject>(ParseObject('DietPlan'))
    ..whereEqualTo('intNumber', 1);

  Subscription subscription = await liveQuery.client.subscribe(query);

  subscription.on(LiveQueryEvent.delete, (value) {
    print('*** DELETE ***: ${DateTime.now().toString()}\n $value ');
    print((value as ParseObject).objectId);
    print((value as ParseObject).updatedAt);
    print((value as ParseObject).createdAt);
    print((value as ParseObject).get('objectId'));
    print((value as ParseObject).get('updatedAt'));
    print((value as ParseObject).get('createdAt'));
  });

  runApp(MyApp());
}
final LiveQuery liveQuery = LiveQuery();
// Copyright 2018 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:convert';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_datetime_picker/flutter_datetime_picker.dart';
import 'package:intl/intl.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:marca_horario/model/data.dart';
import 'package:marca_horario/network_utils/data_utils.dart';
import 'package:http/http.dart';
import 'package:parse_server_sdk/parse_server_sdk.dart';
import 'package:marca_horario/constants.dart';

void myLQ() async {
  Parse().initialize(
    kParseApplicationId,
    kParseServerUrl,
    masterKey: kParseMasterKey,
    clientKey: kParseClientKey,
    debug: true,
    liveQueryUrl: kLiveQueryUrl,
    autoSendSessionId: true,
  );

  var dietPlan = ParseObject('DietPlan')
    ..set('Name', 'Ketogenic')
    ..set('Fat', 65);
  await dietPlan.save();

  var response = await dietPlan.save();
  if (response.success) {
    dietPlan = response.result;
  }

  final LiveQuery liveQuery = LiveQuery();

  QueryBuilder<ParseObject> query =
  QueryBuilder<ParseObject>(ParseObject('DietPlan'))
    ..whereEqualTo('intNumber', 1);

  Subscription subscription = await liveQuery.client.subscribe(query);

  subscription.on(LiveQueryEvent.delete, (value) {
    print('*** DELETE ***: ${DateTime.now().toString()}\n $value ');
    print((value as ParseObject).objectId);
    print((value as ParseObject).updatedAt);
    print((value as ParseObject).createdAt);
    print((value as ParseObject).get('objectId'));
    print((value as ParseObject).get('updatedAt'));
    print((value as ParseObject).get('createdAt'));
  });
}


void main() async{

  Parse().initialize(
    kParseApplicationId,
    kParseServerUrl,
    masterKey: kParseMasterKey,
    clientKey: kParseClientKey,
    debug: true,
    liveQueryUrl: kLiveQueryUrl,
    autoSendSessionId: true,
  );

  var dietPlan = ParseObject('DietPlan')
    ..set('Name', 'Ketogenic')
    ..set('Fat', 65);
  await dietPlan.save();

  var response = await dietPlan.save();
  if (response.success) {
    dietPlan = response.result;
  }

  final LiveQuery liveQuery = LiveQuery();

  QueryBuilder<ParseObject> query =
  QueryBuilder<ParseObject>(ParseObject('DietPlan'))
    ..whereEqualTo('intNumber', 1);

  Subscription subscription = await liveQuery.client.subscribe(query);

  subscription.on(LiveQueryEvent.delete, (value) {
    print('*** DELETE ***: ${DateTime.now().toString()}\n $value ');
    print((value as ParseObject).objectId);
    print((value as ParseObject).updatedAt);
    print((value as ParseObject).createdAt);
    print((value as ParseObject).get('objectId'));
    print((value as ParseObject).get('updatedAt'));
    print((value as ParseObject).get('createdAt'));
  });

  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        localizationsDelegates: [
          GlobalMaterialLocalizations.delegate,
          GlobalWidgetsLocalizations.delegate
        ],
        supportedLocales: [const Locale('pt', 'BR')],
        home: Home()
    );
  }
}

class Home extends StatefulWidget {

  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {

  var _listTiles = List<String>();
  Color _iconColor = Colors.black;
  Color standardIconColor = Colors.black;
  Color alternateIconColor = Colors.green;
  TextEditingController _nameController = TextEditingController();
  var _scaffoldKey = new GlobalKey<ScaffoldState>();
  String standardTileTitle = "Adicione um horário disponível...";
  String _titleTile = "Adicione um horário disponível...";
  String _tileSubtitle = "Edite o nome do funcionário...";
  int _selectedIndexBottomNavBar = 0;
  final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey = new GlobalKey<RefreshIndicatorState>();

  @override
  Widget build(BuildContext context) {
    return RefreshIndicator(
        key: _refreshIndicatorKey,
        onRefresh: () async {
          setState(() {

        });},
        child: Scaffold(
            key: _scaffoldKey,
            floatingActionButton: FloatingActionButton(
              onPressed: () {
                invokeDatePicker();
              },
              child: Icon(Icons.add),
            ),
            bottomNavigationBar: bottomNavigationBar(),
            appBar: AppBar(
              title: Text('Marca Horário'),
            ),
            // body: Center(
            //   child: Text('Hello World'),
            body: bodyStartScreen()
        ),
    );
  }


  Widget bottomNavigationBar(){

    void _onItemTapped(int index) {
      setState(() {
        _selectedIndexBottomNavBar = index;
      });
      print(_selectedIndexBottomNavBar);
      if(_selectedIndexBottomNavBar == 2){
        DatePicker.showDateTimePicker(context,
            showTitleActions: true,
            minTime: DateTime(2020, 1, 1),
            maxTime: DateTime(2021, 12, 31),
            onChanged: (date) {
              print('change $date');
            },
            onConfirm: (date) {
              print('confirm $date');
              _listTiles.add(DateFormat.yMMMEd('pt_BR').add_Hm().format(date).toString());
              _titleTile = DateFormat.yMMMEd('pt_BR').add_Hm().format(date).toString();

              setState(() {

              });
            },
            currentTime: DateTime.now(),
            locale: LocaleType.pt);
      }
    }

    return BottomNavigationBar(
      items: const <BottomNavigationBarItem>[
        BottomNavigationBarItem(
          icon: Icon(Icons.home),
          label: 'Home',
        ),
        BottomNavigationBarItem(
          icon: Icon(Icons.person),
          label: 'Funcionário',
        ),
        BottomNavigationBarItem(
          icon: Icon(Icons.access_time),
          label: 'Marcar',
        ),
      ],
      currentIndex: _selectedIndexBottomNavBar,
      selectedItemColor: Colors.amber[800],
      onTap: _onItemTapped,
    );
  }

  Widget bodyStartScreen(){
    return Column(
      children: [
        //the main title of the screen
        Padding(
          padding: EdgeInsets.all(16.0),
          child: Text("Horários Possíveis",
            style: TextStyle(
                fontSize: 18.0
            ),
          ),
        ),
        //gets available employees and datetimes from the server
        FutureBuilder(builder: (context,snapshot){
          if (snapshot.data != null) {
            List<Data> dataList = snapshot.data;

            return Expanded(
              child: ListView.builder(
                itemBuilder: (_, position) {
                return Card(
                  child: ListTile(
                    title: Text(dataList[position].dateTime),
                    subtitle: Text(dataList[position].employee),
                    trailing: Row(
                      mainAxisSize: MainAxisSize.min,
                      children: <Widget>[
                        IconButton(icon: Icon(Icons.edit), onPressed: () {
                          //Show dialog box to update item
                          showUpdateDialog(dataList[position]);
                        }),
                        IconButton(icon: Icon(Icons.check_circle, color: Colors.green,), onPressed: () {

                        }),
                        //Show dialog box to delete item
                        IconButton(icon: Icon(Icons.delete), onPressed: () {
                          deleteData(dataList[position].objectId);
                        }),
                      ],
                    ),
                  ),
                );
              },
                itemCount: dataList.length,
              ),
            );

          } else {
            return Center(
              child: CircularProgressIndicator(),
            );
          }
        },
          future: getDataList(),
        ),
        Divider(
          color: Colors.black,
        ),
        scheduleTile()
      ],
    );
  }

  void invokeDatePicker(){
    DatePicker.showDateTimePicker(context,
        showTitleActions: true,
        minTime: DateTime(2020, 1, 1),
        maxTime: DateTime(2021, 12, 31),
        onChanged: (date) {
          print('change $date');
        },
        onConfirm: (date) {
          print('confirm $date');
          _listTiles.add(DateFormat.yMMMEd('pt_BR').add_Hm().format(date).toString());
          _titleTile = DateFormat.yMMMEd('pt_BR').add_Hm().format(date).toString();

          setState(() {

          });
        },
        currentTime: DateTime.now(),
        locale: LocaleType.pt);
  }

  void showUpdateDialog(Data data) {

    _nameController.text = data.employee;

    showDialog(context: context,
        builder: (_) => AlertDialog(
          content: Container(
            width: double.maxFinite,
            child: TextField(
              controller: _nameController,
              decoration: InputDecoration(
                labelText: "Atualizar funcionário disponível",
              ),
            ),
          ),
          actions: <Widget>[
            FlatButton(onPressed: () {
              Navigator.pop(context);
              data.employee = _nameController.text;
              updateData(data);
            }, child: Text("Atualizar")),
            FlatButton(onPressed: () {
              Navigator.pop(context);
            }, child: Text("Cancelar")),
          ],
        )
    );

  }

  Widget scheduleTile(){
    return Padding(
      padding: EdgeInsets.only(bottom: 80.0),
      child: Card(
        color: Colors.grey,
        child: ListTile(
          title: Text(_titleTile),
          subtitle: Text(_tileSubtitle),
          trailing: Row(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              IconButton(
                icon: Icon(
                  Icons.edit,
                  color: standardIconColor,
                  size: 20.0,
                ),
                onPressed: () {
                  setState(() {
                    employeeAvailable();
                  });
                },
              ),
              IconButton(
                icon: Icon(
                  Icons.check_circle_outline,
                  color: _iconColor,
                  size: 20.0,
                ),
                onPressed: () {
                  setState(() {
                    (_titleTile != standardTileTitle) ? confirmSchedule() : fillTimeDialog();
                  });
                },
              )
            ],
          ),
        ),
      ),
    );
  }

  void fillTimeDialog(){
    showDialog(context: context,
        builder: (_) => AlertDialog(
          content: Container(
            width: double.maxFinite,
            child: Text("Insira o horário disponível!"),
          ),
          actions: <Widget>[
            FlatButton(onPressed: () {
              Navigator.pop(context);
            }, child: Text("OK")),
          ],
        )
    );
  }

  void employeeAvailable(){
    showDialog(context: context,
        builder: (_) => AlertDialog(
          content: Container(
            width: double.maxFinite,
            child: TextField(
              controller: _nameController,
              decoration: InputDecoration(
                labelText: "Funcionário",
              ),
            ),
          ),
          actions: <Widget>[
            FlatButton(onPressed: () {

              Navigator.pop(context);
              //addTodo();
              setState(() {
                _tileSubtitle = "Disponível: " + _nameController.text;
              });

            }, child: Text("Inserir")),
            FlatButton(onPressed: () {
              Navigator.pop(context);
              setState(() {
                _tileSubtitle = " ";
              });

            }, child: Text("Desfazer")),
          ],
        )
    );
  }

  void confirmSchedule(){
    showDialog(context: context,
        builder: (_) => AlertDialog(
          content: Container(
            width: double.maxFinite,
            child: Text("Confirma disponibilidade?")
          ),
          actions: <Widget>[
            FlatButton(onPressed: () {
              Navigator.pop(context);
              //addTodo();
              addData();
              setState(() {
                _iconColor = alternateIconColor;
                _tileSubtitle = "Disponível: " + _nameController.text;
              });

            }, child: Text("Confirma")),
            FlatButton(onPressed: () {
              Navigator.pop(context);
              setState(() {
                _iconColor = standardIconColor;
                _tileSubtitle = " ";
              });

            }, child: Text("Não")),
          ],
        )
    );
  }

  void addData() {

    _scaffoldKey.currentState.showSnackBar(SnackBar(content: Row(
      children: <Widget>[
        Text("Adicionando informações..."),
        CircularProgressIndicator(),
      ],
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
    ),
      duration: Duration(minutes: 1),
    ));

    Data data = Data(employee: _tileSubtitle, dateTime: _titleTile);

    DataUtils.addData(data)
        .then((res) {

      _scaffoldKey.currentState.hideCurrentSnackBar();

      Response response = res;
      if (response.statusCode == 201) {
        //Successful
        _nameController.text = "";

        _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text("Informações disponibilizadas!"), duration: Duration(seconds: 1),));

        setState(() {
          //Update UI
        });

      }

    });

  }

  void deleteData(String objectId) {

    _scaffoldKey.currentState.showSnackBar(SnackBar(content: Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children:  <Widget>[
        Text("Excluindo disponibilidade..."),
        CircularProgressIndicator(),
      ],
    ),
      duration: Duration(minutes: 1),
    ),);


    DataUtils.deleteData(objectId)
        .then((res) {

      _scaffoldKey.currentState.hideCurrentSnackBar();

      Response response = res;
      if (response.statusCode == 200) {
        //Successfully Deleted
        _scaffoldKey.currentState.showSnackBar(SnackBar(content: (Text("Disponibilidade excluída!")),duration: Duration(seconds: 1),));
        setState(() {

        });
      } else {
        //Handle error
      }
    });

  }

  void updateData(Data data) {

    _scaffoldKey.currentState.showSnackBar(SnackBar(content: Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: <Widget>[
        Text("Atualizando disponibilidade..."),
        CircularProgressIndicator(),
      ],
    ),
      duration: Duration(minutes: 1),
    ),);


    DataUtils.updateData(data)
        .then((res) {

      _scaffoldKey.currentState.hideCurrentSnackBar();

      Response response = res;
      if (response.statusCode == 200) {
        //Successfully Deleted
        _nameController.text = "";
        _scaffoldKey.currentState.showSnackBar(SnackBar(content: (Text("Disponibilidade atualizada!"))));
        setState(() {

        });
      } else {
        //Handle error
      }
    });

  }

  Future <List<Data>> getDataList() async{

    List<Data> dataList = [];

    Response response = await DataUtils.getDataList();
    print("Code is ${response.statusCode}");
    print("Response is ${response.body}");

    if (response.statusCode == 200) {
      var body = json.decode(response.body);
      var results = body["results"];

      for (var data in results) {
        dataList.add(Data.fromJson(data));
      }

    } else {
      //Handle error
    }

    return dataList;
  }
}
import 'dart:convert';

import 'package:http/http.dart';
import 'package:marca_horario/model/data.dart';
import 'package:marca_horario/constants.dart';

class DataUtils {

  //static final String _baseUrl = "https://parseapi.back4app.com/classes/";
  static final String _baseUrl = baseUrl;

  //CREATE
  static Future<Response> addData(Data data) async {
    String apiUrl = _baseUrl + "Data";

    Response response = await post(apiUrl,
      headers: {
        'X-Parse-Application-Id': kParseApplicationId,
        'X-Parse-REST-API-Key': kParseRestApiKey,
        'Content-Type': 'application/json'
      },
      body: json.encode(data.toJson()),
    );

    return response;
  }

  //READ
  static Future getDataList() async{

    String apiUrl = _baseUrl + "Data";

    Response response = await get(apiUrl, headers: {
      'X-Parse-Application-Id' : kParseApplicationId,
      'X-Parse-REST-API-Key' : kParseRestApiKey,
    });

    return response;
  }

  //UPDATE
  static Future updateData(Data data) async{

    String apiUrl = _baseUrl + "Data/${data.objectId}";

    Response response = await put(apiUrl, headers: {
      'X-Parse-Application-Id' : kParseApplicationId,
      'X-Parse-REST-API-Key' : kParseRestApiKey,
      'Content-Type' : 'application/json',
    },
        body: json.encode(data.toJson())
    );

    return response;
  }

  //DELETE
  static Future deleteData(String objectId) async{

    String apiUrl = _baseUrl + "Data/$objectId";

    Response response = await delete(apiUrl, headers: {
      'X-Parse-Application-Id' : kParseApplicationId,
      'X-Parse-REST-API-Key' : kParseRestApiKey,
    });

    return response;
  }
}