i am building a flutter android application and have integrated the resepective api for it, i got a huge problem where when the homescreen of the application opens then it display the category items which are image and title.
and when this homescreen opens then it loads for 2 – 3 seconds to load some of the data and during this loading process the app is very laggy and frame of the phone significantly drops, and after this all of the category data loads , when the data loading finishes then the lagging also stops.
Now, after this completes when i revisit this screen after navigating to some other page of the application then the same process repeats but the loading time will reduce from 2- 3 seconds to 1 -2 seconds and the image loading pattern is also same, first couple of the image and then rest of the others.
Remember that this issue happens even after i used cached network image only and even after it no success and then have also used custom cache manager, and this issue is not only for api data but also the image from the internet that i have used
please look into this matter and help me solve this issue and provide best solution and your suggestions
for the reference i will provide all the releted code for it and will also explain the flow of it:
-
first when the app opens after login, navigator_scaffold.dart will run which contains a appbar and bottom navigation bar
-
the default body of this bottom bar is homescreen
-
homescreen contains two widgets image slider at top and then category
-
the category data is displayed in the category section
and i have also provided category model class and category provider classhome_screen.dart
import ‘package:flutter/material.dart’;
import ‘package:service_pro_user/UI/home_screen/widgets/Image_slider.dart’;
import ‘package:service_pro_user/UI/home_screen/widgets/category.dart’;class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});@override
State createState() => _HomeScreenState();
}class _HomeScreenState extends State {
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 10, right: 10),
child: SingleChildScrollView(
child: Column(
children: [
ImageSlider(),
Category(),
],
),
),
);
}
}
category.dart
import ‘package:cached_network_image/cached_network_image.dart’;
import ‘package:flutter/material.dart’;
import ‘package:lottie/lottie.dart’;
import ‘package:provider/provider.dart’;
import ‘package:service_pro_user/Provider/category_provider.dart’;
import ‘package:service_pro_user/Provider/search_provider/service_search_provider.dart’;
import ‘package:service_pro_user/UI/home_screen/widgets/service.dart’;
import ‘package:flutter_cache_manager/flutter_cache_manager.dart’;
import ‘package:service_pro_user/UI/service_providers/service_providers.dart’;class CustomCacheManager extends CacheManager {
static const key = “customCacheKey”;CustomCacheManager()
: super(Config(
key,
stalePeriod: const Duration(days: 7),
maxNrOfCacheObjects: 1000,
));
}class Category extends StatefulWidget {
const Category({super.key});@override
State createState() => _CategoryState();
}class _CategoryState extends State {
TextEditingController searchController = TextEditingController();
@override
void initState() {
super.initState();
Provider.of(context, listen: false).getCategories();
}Future showSearchResults(BuildContext context) async {
final searchServiceData =
Provider.of(context, listen: false).searchData;
await showDialog(
context: context,
builder: (context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15.0),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: const EdgeInsets.all(16.0),
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(15.0),
topRight: Radius.circular(15.0),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
‘Search Results’,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
GestureDetector(
onTap: () {
Navigator.of(context).pop();
},
child: const Icon(
Icons.close,
color: Colors.white,
),
),
],
),
),
Flexible(
child: searchServiceData.isEmpty
? const Padding(
padding: EdgeInsets.all(16.0),
child: Text(
‘No results found.’,
style: TextStyle(fontSize: 16),
),
)
: ListView.builder(
shrinkWrap: true,
itemCount: searchServiceData.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ServiceProviders(
serviceData: searchServiceData[index]),
),
);
},
child: Column(
children: [
ListTile(
leading: const Icon(Icons.search),
title: Text(
searchServiceData[index][‘Name’].toString(),
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
subtitle: Text(
searchServiceData[index][‘Description’]
.toString(),
),
),
const Divider(),
],
),
);
},
),
),
],
),
);
},
);
}@override
Widget build(BuildContext context) {
return Consumer(
builder: (context, categoryProvider, child) {
if (categoryProvider.categories.isEmpty) {
return const Center(
child: CircularProgressIndicator(),
);
} else {
final categoryData = categoryProvider.categories;
return SingleChildScrollView(
child: Column(
children: [
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Theme.of(context).primaryColor,
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
const Text(
‘CATEGORIES’,
style: TextStyle(fontSize: 22, color: Colors.white),
),
const SizedBox(width: 30),
Expanded(
child: TextField(
controller: searchController,
decoration: InputDecoration(
contentPadding:
EdgeInsets.symmetric(vertical: 10.0),
hintText: ‘Search Services’,
hintStyle: TextStyle(color: Colors.white54),
prefixIcon:
Icon(Icons.search, color: Colors.white),
suffixIcon: IconButton(
icon: Icon(Icons.send, color: Colors.white),
onPressed: () async {
try {
await Provider.of(context,
listen: false)
.setSearchService(
context, searchController.text);
await showSearchResults(context);
} catch (e) {
print(‘search failed: $e’);
}
searchController.clear();
},
),
filled: true,
fillColor: Colors.white.withOpacity(0.2),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
borderSide: BorderSide(
color: Colors.white,
width: 1.0,
),
),
),
style: TextStyle(color: Colors.white),
cursorColor: Colors.white,
),
),
],
),
),
),
const SizedBox(
height: 10,
),
GridView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: categoryData.length,
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 10,
),
itemBuilder: (context, index) {
final categories = categoryData[index];
String image = categories.image.toString();
image = image.replaceFirst(‘localhost’, ‘20.52.185.247’);
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
Service(category: categories),
),
);
},
child: Column(
children: [
Expanded(
child: Container(
width: 180,
height: 150,
child: ClipRRect(
borderRadius: BorderRadius.circular(5),
child: FittedBox(
fit: BoxFit.fill,
child: CachedNetworkImage(
imageUrl: image,
cacheManager: CustomCacheManager(),
placeholder: (context, url) => Lottie.asset(
‘assets/lotties_animation/loading.json’),
errorWidget: (context, url, error) =>
Lottie.asset(
‘assets/lotties_animation/error.json’)),
),
),
),
),
Text(
categories.name.toString(),
style: const TextStyle(
fontWeight: FontWeight.bold, fontSize: 16),
),
],
),
);
}),
],
),
);
}
},
);
}
}
category model
class CategoryModel {
String? id;
String? name;
String? description;
List? services;
String? image;
String? createdAt;
String? updatedAt;CategoryModel({
this.id,
this.name,
this.description,
this.services,
this.image,
this.createdAt,
this.updatedAt,
});CategoryModel.fromJson(Map<String, dynamic> json) {
id = json[‘_id’];
name = json[‘Name’];
description = json[‘Description’];
services = json[‘Services’];
image = json[‘Image’];
createdAt = json[‘createdAt’];
updatedAt = json[‘updatedAt’];
}Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data[‘_id’] = id;
data[‘Name’] = name;
data[‘Description’] = description;
data[‘Services’] = services;
data[‘Image’] = image;
data[‘createdAt’] = createdAt;
data[‘updatedAt’] = updatedAt;return data;
}
}
category_provider
import ‘dart:convert’;import ‘package:flutter/cupertino.dart’;
import ‘package:service_pro_user/Models/category_model.dart’;
import ‘package:http/http.dart’ as http;class CategoryProvider extends ChangeNotifier {
List _categories = [];List get categories => _categories;
Future getCategories() async {
final response =
await http.get(Uri.parse(‘http://20.52.185.247:8000/category’));if (response.statusCode == 200) { final categoryData = jsonDecode(response.body)['data'] as List; _categories = categoryData.map((e) => CategoryModel.fromJson(e)).toList(); notifyListeners(); } else { throw Exception('Failed to load categories'); }
}
}
Nabin Adhikari is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.