flutterentity-frameworkflutter-dependenciesflutter-animation

Flutter widgets (android app) are flickering while scrolling


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();
  }
}

Solution

  • 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