I have a background that is drawn using Flutter custom painter and it uses the Random() function to draw shapes at random positions (ex.: stars), also I have a widget that has a timer, this timer ticks every second and every second I use emit() inside my cubit to update my screen.
My problem is when the screen gets updated every second, the background also gets updated with new positions for my shapes, and every second nearly two rebuilds which means that my background rebuilds itself two times for every second (that's a disaster for the Memory), besides this background must be static, so how to prevent this unnecessary rebuilds?
my stack widget which holds the timer and background behind it: my backgrounds are NightClipper(), LightClipper() and DayTimeline() widgets they are being rebuilt although they're not included in my BlocConsumer()
Stack(
alignment: AlignmentDirectional.center,
fit: StackFit.expand,
children: [
ClipPath(
clipper: NightClipper(
portrait: _portrait,
lightRegionFraction: light,
nightRegionFraction: night,
),
child: CustomPaint(
painter: DayNightView(
portrait: _portrait,
lightRegionFraction: light,
nightRegionFraction: night,
),
),
),
ClipPath(
clipper: LightClipper(
portrait: _portrait,
lightRegionFraction: light,
nightRegionFraction: night,
),
child: CustomPaint(
painter: DayLightView(
portrait: _portrait,
lightRegionFraction: light,
nightRegionFraction: night,
),
),
),
CustomPaint(
painter: DayTimeline(
portrait: _portrait,
fajrFraction: light,
sunriseFraction: 0.2,
dhuhrFraction: 0.45,
asrFraction: 0.6,
maghribFraction: night,
ishaFraction: 0.8,
),
),
BlocConsumer<HomeScreenMainWidgetCubit, HomeScreenMainWidget>(
listener: (context, value) {
context.read<HomeScreenMainWidgetCubit>().refresh();
},
builder: (context, value) {
return Stack(
alignment: AlignmentDirectional.center,
fit: StackFit.expand,
children: [
CustomPaint(
foregroundPainter: NextPrayerIndicator(
indicator: value.indicatorValue,
portrait: _portrait,
),
painter: Background(
portrait: _portrait,
),
),
CustomPaint(
painter: CountdownTimer(
timer: value.nextPrayerTimer,
portrait: _portrait,
),
),
CustomPaint(
painter: PrayerTitle(
title: value.nextPrayerTitle,
portrait: _portrait,
),
),
],
);
},
),
],
);
My provider code
BlocProvider(
create: (_) => HomeScreenMainWidgetCubit()..init(),
),
My cubit code
class HomeScreenMainWidgetCubit extends Cubit<HomeScreenMainWidget> {
HomeScreenMainWidgetCubit()
: super(HomeScreenMainWidget(
indicatorValue: 0.0,
nextPrayerTitle: '...',
nextPrayerTimer: Duration(
hours: 0,
minutes: 0,
seconds: 0,
),
));
/*
0 -> sunrise
1 -> sunset / maghrib
2 -> fajr
3 -> dhuhr
4 -> asr
5 -> isha
*/
Timer? _timer;
List<Duration>? _prayerTimes;
void init() {
bool gps = SharedPreferencesService.getGPSBool() ?? false;
if (gps == true) {
Position? position = SharedPreferencesService.getPosition();
_prayerTimes = PrayerTimes.getAuto(
position!,
DateTime.now(),
);
} else {
String country = SharedPreferencesService.getCountry() ?? 'Egypt';
String state = SharedPreferencesService.getState() ?? 'Cairo';
_prayerTimes = PrayerTimes.getManual(
country,
state,
DateTime.now(),
);
}
refresh();
}
void refresh() {
_timer = Timer(Duration(seconds: 1), () {
emit(HomeScreenMainWidget(
indicatorValue: NextPrayer.getIndicatorValue(
_prayerTimes!,
DateTime.now(),
),
nextPrayerTitle: NextPrayer.getTitle(
_prayerTimes!,
DateTime.now(),
),
nextPrayerTimer: NextPrayer.getTimer(
_prayerTimes!,
DateTime.now(),
),
));
});
}
@override
Future<void> close() {
_timer?.cancel();
return super.close();
}
}
Note that in my custom painter, my shouldRepaint function returns false, so I don't know why my background gets updated on each emit.
edits: here's my stateless widget
class HomeScreen extends StatelessWidget {
const HomeScreen({
Key? key,
}) : super(key: key);
static String id = 'home_screen';
@override
Widget build(BuildContext context) {
Orientation orientation = MediaQuery.of(context).orientation;
Size size = MediaQuery.of(context).size;
bool isPortrait = !((size.width > kPhoneMaximumScreenWidth) ||
(orientation == Orientation.landscape));
return MultiBlocProvider(
providers: [
BlocProvider(
create: (_) => HomeScreenMainWidgetCubit()..init(),
),
],
child: Stack(
alignment: AlignmentDirectional.center,
fit: StackFit.expand,
children: [
isPortrait
? Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
// flex: 5,
child: Semantics(
// todo build semantics
child: ClipRect(
clipper: BackgroundClipper(
portrait: isPortrait,
),
child: HomeScreenStackDesign(
portrait: isPortrait,
),
),
),
),
],
)
: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
// flex: 2,
child: Semantics(
// todo build semantics
child: ClipRect(
clipper: BackgroundClipper(
portrait: isPortrait,
),
child: HomeScreenStackDesign(
portrait: isPortrait,
),
),
),
),
],
),
],
),
);
}
}