The database rendered elements are multiplying on screen every time, I click off the screen and then back onto the screen.
Here is the code that is creating those elements on screen:
class AlarmScreen extends StatefulWidget {
const AlarmScreen({Key? key}) : super(key: key);
@override
_AlarmScreenState createState() => _AlarmScreenState();
}
class _AlarmScreenState extends State<AlarmScreen> {
AlarmHelper _alarmHelper = AlarmHelper();
Future<List<AlarmInfo>>? _alarms;
@override
void deactivate() {
super.deactivate();
}
@override
void initState() {
_alarmHelper.initializeDatabase().then((value) => print('------------dB initialized'));
_alarms = _alarmHelper.getAlarm();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFF2D2F41),
appBar: PreferredSize(preferredSize: Size.fromHeight(50),
child: CustomAppBar("Alarm")),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget> [
Expanded(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 45, vertical: 10),
child: FutureBuilder<List<AlarmInfo>>(
future: _alarms,
builder: (context, snapshot)
{
if(snapshot.hasData){
return ListView(
children: snapshot.data!.map<Widget>((alarms) {
return Container(
margin: EdgeInsets.only(bottom: 32),
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Icon(Icons.label, color: Colors.white, size:
24,),
SizedBox(width: 8,),
Text(alarms.title, style: TextStyle(color:
Colors.white, fontFamily: 'avenir'),),
],
),
Switch(value: alarms.isPending == 1 ? true : false, onChanged: (bool value){},
activeColor: Colors.white,)
],
),
Text('Mon-Fri', style: TextStyle(color:
Colors.white, fontFamily: 'avenir'),),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text( alarms.dateTime.hour.toString().padLeft(2, "0") ":" alarms.dateTime.minute.toString().padLeft(2, "0") , style: TextStyle(color:
Colors.white, fontFamily: 'avenir',
fontWeight: FontWeight.w700,
fontSize: 24),),
IconButton(onPressed: (){
_alarmHelper.deleteAlarm(alarms.id);
setState(() {
});
}, icon: Icon(Icons.delete, color: Colors.white, size: 24,))
],
),
],
),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: GradientColors.sunset,
begin: Alignment.centerLeft,
end: Alignment.centerRight
),
borderRadius: BorderRadius.all(Radius.circular(24)),
boxShadow: [
BoxShadow(
color: GradientColors.sunset.last.withOpacity(0.4),
blurRadius: 5, spreadRadius: 2, offset: Offset(4,4)
)
]
),
);
}).followedBy([
DottedBorder(
child: Container(
decoration: BoxDecoration(
color: Color(0xff3C3F69),
borderRadius: BorderRadius.all(Radius.circular(24))
),
alignment: Alignment.center,
// color: Colors.red,
height: 110,
child: MaterialButton(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Icon(Icons.control_point, color: Colors.white,
size: 30,),
SizedBox(height: 8,),
Center(
child: Text('Add Alarm', style: TextStyle(
fontSize: 15, fontFamily: 'avenir',
color: Colors.white,
fontWeight: FontWeight.w700,
),),
)
],
mainAxisAlignment: MainAxisAlignment.center,
),
onPressed: (){
Navigator.push(context, MaterialPageRoute(builder: (context){
return AddAlarmScreen();
}));
},
),
),
strokeWidth: 3,
color: Colors.white,
borderType: BorderType.RRect,
radius: Radius.circular(24),
dashPattern: [6, 6, 6],
),
]).toList(),
);}
else{
return Center(
child: Text('Loading...', style: TextStyle(
color: Colors.white,
fontSize: 20
),),
);
}
}
),
),
),
],
)
);
}
}
This is my code for the alarmHelper:
final String tableName = 'alarm';
final String id = 'id';
final String title = 'title';
final String dateTime = 'dateTime';
final String color = 'gradientColorIndex';
final String isPending = 'isPending';
class AlarmHelper{
static Database? _database;
static AlarmHelper? _alarmHelper;
AlarmHelper._createInstance();
factory AlarmHelper() {
if (_alarmHelper == null){
_alarmHelper = AlarmHelper._createInstance();
}
return _alarmHelper!;
}
Future<Database?> get database async{
if (_database == null){
_database = await initializeDatabase();
}
return _database!;
}
Future<Database> initializeDatabase() async{
var dir = await getDatabasesPath();
var path = dir "alarm.db";
var database = await openDatabase(path, version: 1, onCreate: (db, version){
db.execute('''
create table $tableName(
$id integer primary key autoincrement,
$title text not null,
$dateTime text not null,
$color integer,
$isPending integer not null
)
''');
}
);
return database;
}
void insetAlarm(AlarmInfo alarmInfo) async{
var db = await this.database;
var result = await db?.insert(tableName, alarmInfo.toMap());
print(result);
}
Future<List<AlarmInfo>> getAlarm() async{
var result;
var db = await this.database;
result = await db?.query(tableName);
result.forEach((element) {
var alarmInfo = AlarmInfo.fromMap(element);
alarms.add(alarmInfo);
}
);
return alarms;
}
void deleteAlarm(idOfAlarm) async{
var db = await this.database;
db?.delete(tableName, where: 'id = ?', whereArgs: [idOfAlarm]);
}
}
The problem in more detail is that This is the screen currently with a single alarm on it.
But when I click off the screen and back on it, I will see the same element twice and this number increases by 1 every time I click off the screen and back on it, this is what it looks like.
CodePudding user response:
The code for AlarmHelper
is incomplete, but looks with alarms.add(alarmInfo);
you're adding new items to the alarms
list, so each new call to getAlarms()
returns a list with one more item.