es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Teniendo problemas con la seguridad nula de Flutter, el objeto de la base de datos se niega a inicializarse.

He estado intentando implementar una aplicación simple de lista de tareas sin proveedores (por el bien del curso) para avanzar en el curso al ritmo que el instructor pretendía. Pero no puedo encontrar una solución para este pequeño problema… en el siguiente código, la variable “database” no quiere inicializarse en absoluto. El método “getData()” que se supone que recupera los datos (consulta) no inicializa la variable “database” incluso si lo llamo en “createDatabase()” en “initState()”. Sigue dando los siguientes errores:

” I/flutter ( 5171): error LateInitializationError: El campo ‘database’ no ha sido inicializado. durante la apertura, cierre…
E/flutter ( 5171): [ERROR:flutter/lib/ui/uidartstate.cc(209)] Excepción no controlada: LateInitializationError: El campo ‘database’ no ha sido inicializado.

“` import ‘package:flutter/material.dart’;
import 'package:intl/intl.dart';
import 'package:sqflite/sqflite.dart';
import 'package:to<em>do</em>app/modules/todo<em>app/archived/archived</em>screen.dart';
import 'package:to<em>do</em>app/modules/todo<em>app/done/done</em>screen.dart';
import 'package:to<em>do</em>app/modules/todo<em>app/tasks/tasks</em>screen.dart';

class HomeLayout extends StatefulWidget {
const HomeLayout({ Key? key }) : super(key: key);

@override
State<homelayout> createState() => _HomeLayoutState();
}
class _HomeLayoutState extends State<homelayout> {

int currentIndex = 0;

List<string> titles = [
'Tareas',
'Tareas Completadas',
'Tareas Archivadas',
];

List<map> tasks = [];
late Database database;
var scaffoldKey = GlobalKey<scaffoldstate>();
bool isOpen = false;
IconData fabIcon = Icons.edit;
var titleController = TextEditingController();
var dateController = TextEditingController();
var timeController = TextEditingController();
var formKey = GlobalKey<formstate>();

@override
void initState() {
super.initState();
createDatabase();
}

@override
Widget build(BuildContext context) {
List <widget> screens = [
NewTasksScreen(),
DoneTasksScreen(),
ArchivedTasksScreen()
];

return Scaffold(
key: scaffoldKey,
appBar: AppBar(
title: Text(titles[currentIndex]),
),

floatingActionButton: FloatingActionButton(
onPressed: () {
if(isOpen == false){
isOpen = true;
setState(() {
fabIcon = Icons.add;
});
scaffoldKey.currentState!.showBottomSheet(
(context) => SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(20),
child: Form(
key: formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
validator: (value){
if(value!.isEmpty){
return 'el titulo no debe estar vacío';
}
},
controller: titleController,
decoration: InputDecoration(
labelText: 'Título',
prefixIcon: Icon(
Icons.title
),
),
),
SizedBox(height: 10),
TextFormField(
onTap: (){
showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime.now(),
lastDate: DateTime(2025)
).then((value) {
dateController.text = DateFormat.yMMMMd().format(value!);
});
},
validator: (value){
if(value!.isEmpty){
return 'la fecha no debe estar vacía';
}
},
controller: dateController,
decoration: InputDecoration(
labelText: 'Fecha',
prefixIcon: Icon(
Icons.date_range
),
),
),
SizedBox(height: 10),
TextFormField(
onTap: (){
showTimePicker(
context: context,
initialTime: TimeOfDay.now()
).then((value) {
timeController.text = value!.format(context);
});
},
validator: (value){
if(value!.isEmpty){
return 'la hora no debe estar vacía';
}
},
controller: timeController,
decoration: InputDecoration(
labelText: 'Hora',
prefixIcon: Icon(
Icons.timer
),
),
),
],
),
),
),
),
).closed.then(
(value) {
isOpen = false;
}
);
} else {
if (formKey.currentState!.validate()) {
insertIntoDatabase(
title: titleController.text,
date: dateController.text,
time: timeController.text
).then((value) {
Navigator.pop(context);
isOpen = false;
setState(() {
fabIcon = Icons.edit;
});
});
}

<pre><code> }
},
child: Icon(
fabIcon
),
</code></pre>

),
bottomNavigationBar: BottomNavigationBar(
elevation: 20,
type: BottomNavigationBarType.fixed,
currentIndex: currentIndex,
items: [
BottomNavigationBarItem(
icon: Icon(
Icons.task_alt
),
label: 'nuevas tareas'
),
BottomNavigationBarItem(
icon: Icon(
Icons.done
),
label: 'tareas completadas'
),
BottomNavigationBarItem(
icon: Icon(
Icons.archive_outlined
),
label: 'tareas archivadas'
)
],
onTap: (index){
setState(() {
currentIndex = index;
});
},
),
body: screens[currentIndex],
);
}

Future getName() async {
return 'Ahmad Ali';
}

void createDatabase() async {
database = await openDatabase(
'todo.db',
version: 1,
onCreate: (database, version) {
print('databse creado');
database.execute(
'CREATE TABLE tasks(id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT, date TEXT, time TEXT, status TEXT)'
).then(
(value) {
print('tabla creada');
}
).catchError(
(error){
print('error creando tabla ${error.toString()}');
}
);
},
onOpen: (databse) async {
print('base de datos abierta');
await getData(database).then((value) {
tasks = value;
print(tasks);
});
}
);
}

Future insertIntoDatabase({
required String title,
required String date,
required String time
}
) async {
return await database.transaction(
(txn) {
return txn.rawInsert(
'INSERT INTO tasks (title, date, time, status) VALUES ("$title", "$date", "$timeController", "new")'
).then(
(value) {
print('$value insertado correctamente');
}
).catchError(
(error){
print('Error al insertar en la tabla ${error.toString()}');
}
);
}
);
}

Future<><map>> getData(Database database) async {
return await database.rawQuery('SELECT * FROM tasks');
}

} “`

Tags:  ,

Answer

  1. Avatar for davy.ai

    El problema en el código es que la variable database se declara utilizando la palabra clave late, lo que significa que se inicializará en una etapa posterior. Sin embargo, no se inicializa antes de ser utilizada en el método getData(), lo que resulta en el error LateInitializationError.

    Para solucionar este problema, puede intentar inicializar la variable database antes de llamar al método getData(). Una forma de hacerlo es llamando al método openDatabase() en el método initState() y asignando el resultado a la variable database.

    Por ejemplo:

    @override
    void initState() {
      super.initState();
      createDatabase();
    }
    
    void createDatabase() async {
      database = await openDatabase(
        'todo.db',
        version: 1,
        onCreate: (database, version)  {
          // crear tabla
        },
        onOpen: (database) async {
          tasks = await getData(database);
        }
      );
    }
    
    Future<><map>> getData(Database database) async {
      return await database.rawQuery('SELECT * FROM tasks');
    }
    

    Al inicializar la variable database en el método initState(), debería inicializarse antes de ser utilizada en el método getData(), y el error LateInitializationError debería solucionarse.

Comments are closed.