My Flutter widgets are flickering while scrolling on low-end phones, and I don't know the reason. I used Image.network, and I get the image URL and text from GitHub. Based on how many data entries are in the GitHub JSON file, it calls a function and builds the widget. After i scrolling games() function portions is shaking in low end device. (i already tried image caching )
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:http/http.dart' as http;
import 'package:share_plus/share_plus.dart';
import 'package:url_launcher/url_launcher.dart';
class Games extends StatelessWidget {
const Games({super.key});
//getting other json file
Future<List<Map<String, dynamic>>> fetchOthersData() async {
const url = 'XXXXXXXX';
// Load token from .env file
final token = dotenv.env['GITHUB_TOKEN'];
if (token == null) {
throw Exception('GitHub token not found.');
}
final headers = {
'Authorization': 'token $token',
};
// Append cache-busting parameters to the URL
final uri = Uri.parse(
'$url?v=${DateTime.now().millisecondsSinceEpoch}&random=${DateTime.now().microsecondsSinceEpoch}');
try {
// Use the URI with cache-busting parameters and authorization headers
final response = await http.get(uri, headers: headers);
if (response.statusCode == 200) {
// Parse the JSON response
List<dynamic> data = json.decode(response.body);
return data.map((item) => item as Map<String, dynamic>).toList();
} else {
// Handle errors
throw Exception('Failed to load data from $url');
}
} catch (e) {
throw Exception('Failed to load data');
}
}
Widget games(otherimage, othername, otherplatform, othersubtitle, otherprice,
otherrating, otherredirecturl) {
final Uri url = Uri.parse(otherredirecturl);
// Function to launch the URL
Future<void> launchWebsite() async {
if (!await launchUrl(url, mode: LaunchMode.externalApplication)) {
throw 'Could not launch $otherredirecturl';
}
}
// Function to share the link
void shareLink() {
Share.share(
'Exciting news! 🎉 $othername is now available for FREE! : https://play.google.com/store/apps/details?id=in.TCode.gameradar');
}
return Padding(
padding: const EdgeInsets.only(left: 7, right: 7, top: 10),
child: GestureDetector(
onTap: launchWebsite,
onLongPress: shareLink,
child: Container(
width: double.infinity,
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10)),
color: Color.fromARGB(255, 11, 22, 30),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
//image
ClipRRect(
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(10)),
child: SizedBox(
height: 150,
width: double.infinity,
child: Image.network(
otherimage,
fit: BoxFit.fill,
loadingBuilder: (context, child, loadingProgress) {
if (loadingProgress == null) {
return child;
}
return const Center(
child: CircularProgressIndicator(
strokeWidth: 2.0,
valueColor: AlwaysStoppedAnimation<Color>(
Color.fromARGB(255, 3, 213, 192)),
),
);
},
errorBuilder: (context, error, stackTrace) => const Icon(
Icons.broken_image,
size: 60,
color: Color.fromARGB(197, 136, 193, 232),
),
),
),
),
//name
Padding(
padding: const EdgeInsets.only(left: 8, top: 8),
child: Text(
'$othername ($otherplatform)',
style: const TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w600),
overflow: TextOverflow.ellipsis,
),
),
Padding(
padding: const EdgeInsets.only(left: 8, bottom: 8),
child: Text(
othersubtitle,
style: const TextStyle(
color: Color.fromARGB(197, 136, 193, 232),
fontSize: 12,
fontWeight: FontWeight.w600),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
),
Padding(
padding: const EdgeInsets.only(left: 8, bottom: 5),
child: Text(
'Price : $otherprice.00',
style: const TextStyle(
color: Color.fromARGB(255, 3, 213, 192),
fontSize: 12,
fontWeight: FontWeight.w600),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
),
Padding(
padding: const EdgeInsets.only(left: 8, bottom: 8),
child: Text(
'Ratings : $otherrating',
style: const TextStyle(
color: Color.fromARGB(255, 3, 213, 192),
fontSize: 12,
fontWeight: FontWeight.w600),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
),
],
),
),
),
);
}
Widget othersshow() {
return Container(
width: double.infinity,
decoration: const BoxDecoration(
color: Color.fromARGB(50, 0, 9, 21),
),
child: FutureBuilder<List<Map<String, dynamic>>>(
future: fetchOthersData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: Padding(
padding: EdgeInsets.all(15.0),
child: SizedBox(
width: 20.0,
height: 20.0,
child: CircularProgressIndicator(),
),
),
);
} else if (snapshot.hasError) {
return const Center(
child: Text(
'No internet connection',
style: TextStyle(color: Colors.blueGrey),
),
);
} else if (!snapshot.hasData || snapshot.data!.isEmpty) {
return const Center(
child: Text(
'No data available',
style: TextStyle(color: Colors.blueGrey),
),
);
}
final apps = snapshot.data!;
return ListView.builder(
itemCount: apps.length,
itemBuilder: (context, index) {
final other = apps[index];
return games(
other['otherimage_url'] ?? '',
other['othername'] ?? '',
other['otherotherplatform'] ?? '',
other['othersubtitle'] ?? '',
other['otherprice'] ?? '',
other['otherrating'] ?? '',
other['otherredirect_url'] ?? '',
);
},
);
},
),
);
}
@override
Widget build(BuildContext context) {
return othersshow();
}
}
If your problem persists with caching images, the reason can be impeller. Impeller makes UI glitches on some old devices and emulators which doesn't support Vulkan. So please try to disable the impeller and see if that works.
flutter run -d emulator-5554 --no-enable-impeller