i'm learning to use Cubit, Initially the application runs without any errors when I do the likeArticle, but when I do the like method continuously or too often an Unhandled Exception will occur. This my code:
//article_cubit.dart
class ArticleCubit extends Cubit<ArticleState> {
final CreateArticleUseCase createArticleUseCase;
final ReadArticlesUseCase readArticlesUseCase;
final LikeArticleUseCase likeArticleUseCase;
ArticleCubit({
required this.createArticleUseCase,
required this.readArticlesUseCase,
required this.likeArticleUseCase,
}) : super(ArticleInitial());
Future<void> createArticle({required ArticleEntity articleEntity}) async {
try {
await createArticleUseCase.call(articleEntity);
} on SocketException catch (_) {
emit(ArticleFailure());
} catch (_) {
emit(ArticleFailure());
}
}
Future<void> getArticles({required ArticleEntity articleEntity}) async {
emit(ArticleLoading());
try {
final streamResponse = readArticlesUseCase.call(articleEntity);
streamResponse.listen(
(articles) {
debugPrint("ArticleCubit[getArticles]: emit(ArticleLoaded())");
emit(ArticleLoaded(articles: articles));
},
);
} on SocketException catch (_) {
emit(ArticleFailure());
} catch (_) {
emit(ArticleFailure());
}
}
Future<void> likeArticle({required ArticleEntity articleEntity}) async {
try {
await likeArticleUseCase.call(articleEntity);
} on SocketException catch (_) {
emit(ArticleFailure());
} catch (_) {
emit(ArticleFailure());
}
}
}
This my ArticlePage:
class ArticlePage extends StatelessWidget {
final UserEntity currentUser;
const ArticlePage({super.key, required this.currentUser});
#override
Widget build(BuildContext context) {
debugPrint("ArticlePage[build]: Building!!");
return Scaffold(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0.0,
title: Text(
"Article",
style: TextStyle(color: AppColor.primaryColor, fontSize: 25),
),
actions: [
currentUser.role == "admin"
? Padding(
padding: const EdgeInsets.only(right: 10.0),
child: InkWell(
onTap: () {
Navigator.pushNamed(
context,
PageConst.uploadArticlePage,
arguments: currentUser,
);
},
child: Icon(Icons.create, color: AppColor.primaryColor),
),
)
: const SizedBox(),
],
),
body: BlocProvider<ArticleCubit>(
create: (context) => di.sl<ArticleCubit>()
..getArticles(articleEntity: const ArticleEntity()),
child: BlocBuilder<ArticleCubit, ArticleState>(
builder: (context, articleState) {
if (articleState is ArticleLoading) {
return const Center(
child: CircularProgressIndicator(
color: Colors.black,
));
}
if (articleState is ArticleFailure) {
toast("Some failure occured while creating the article");
}
if (articleState is ArticleLoaded) {
return articleState.articles.isEmpty
? _noPostsWidget()
: ListView.builder(
itemCount: articleState.articles.length,
itemBuilder: (context, index) {
final article = articleState.articles[index];
return BlocProvider(
create: (context) => di.sl<ArticleCubit>(),
child: SingleArticleWidget(articleEntity: article),
);
},
);
}
return const Center(
child: CircularProgressIndicator(
color: Colors.black,
));
},
),
),
);
}
Center _noPostsWidget() {
return Center(
child: Text(
"No Posts",
style: TextStyle(
color: AppColor.primaryColor,
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
);
}
}
and this my SingleArticleWidget (like Card widget);
class SingleArticleWidget extends StatefulWidget {
final ArticleEntity articleEntity;
const SingleArticleWidget({
Key? key,
required this.articleEntity,
}) : super(key: key);
#override
State<SingleArticleWidget> createState() => _SingleArticleWidgetState();
}
class _SingleArticleWidgetState extends State<SingleArticleWidget> {
String _currentUid = "";
#override
void initState() {
di.sl<GetCurrentUidUseCase>().call().then((uid) {
setState(() {
_currentUid = uid;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 10.0),
child: Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
offset: const Offset(5, 10),
blurRadius: 10,
color: AppColor.gradientSecond.withOpacity(0.3),
),
],
),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 5.0, vertical: 5.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// [TopSection]: Image and title
Material(
color: Colors.transparent,
child: InkWell(
onTap: () {
Navigator.pushNamed(
context,
PageConst.detailArticlePage,
arguments: AppEntity(
uid: _currentUid,
articleId: widget.articleEntity.articleId,
creatorUid: widget.articleEntity.creatorUid,
),
);
},
child: Ink(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Image
Container(
width: double.infinity,
height: size.height * 0.25,
decoration: BoxDecoration(
// color: Colors.red,
borderRadius: BorderRadius.circular(10),
),
child: imageBoxWidget(
imageUrl: widget.articleEntity.articleImageUrl),
),
AppSize.sizeVer(10),
// Title
Text(
widget.articleEntity.title!.length > 63
? "${widget.articleEntity.title!.substring(0, 63)}..."
: widget.articleEntity.title!,
style: AppTextStyle.kTitleTextStyle
.copyWith(fontSize: 19),
),
],
),
),
),
),
AppSize.sizeVer(10),
// User Tag
// [BottomSection]: Include Usertag, like button, total like.
Row(
children: [
// [Container]: User tag
Container(
decoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(20.0),
),
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 7.0,
vertical: 3.0,
),
child: FittedBox(
child: Row(
children: [
SizedBox(
width: 25,
height: 25,
child: ClipRRect(
borderRadius: BorderRadius.circular(15),
child: profileWidget(
imageUrl:
widget.articleEntity.userProfileUrl),
),
),
AppSize.sizeHor(8),
Text(
widget.articleEntity.username!,
style: AppTextStyle.kTitleTextStyle.copyWith(
fontSize: 15,
color: Colors.white,
),
)
],
),
),
),
),
const Spacer(),
// [Text]: Total Likes.
Text(
'${widget.articleEntity.totalLikes} likes',
style: TextStyle(
color: AppColor.primaryColor,
fontWeight: FontWeight.bold,
),
),
AppSize.sizeHor(5),
// [Button]: Like Button.
InkWell(
onTap: _likeArticle,
child: Icon(
widget.articleEntity.likes!.contains(_currentUid)
? Icons.favorite
: Icons.favorite_outline,
color: widget.articleEntity.likes!.contains(_currentUid)
? Colors.red
: AppColor.primaryColor,
),
)
],
),
AppSize.sizeVer(10),
],
),
),
),
);
}
void _likeArticle() {
BlocProvider.of<ArticleCubit>(context).likeArticle(
articleEntity: ArticleEntity(
articleId: widget.articleEntity.articleId,
),
);
}
}
for ArticleCubit.getArticles.<anonymous closure> this line reffer to emit(ArticleLoaded(articles: articles));. This my problem from Debug Console:
E/flutter (14310): #0 BlocBase.emit
E/flutter (14310): #1 ArticleCubit.getArticles.<anonymous closure>
E/flutter (14310): #2 _RootZone.runUnaryGuarded (dart:async/zone.dart:1586:10)
E/flutter ( 7916): #3 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:339:11)
E/flutter ( 7916): #4 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
E/flutter ( 7916): #5 _ForwardingStreamSubscription._add (dart:async/stream_pipe.dart:123:11)
E/flutter ( 7916): #6 _MapStream._handleData (dart:async/stream_pipe.dart:218:10)
E/flutter ( 7916): #7 _ForwardingStreamSubscription._handleData (dart:async/stream_pipe.dart:153:13)
E/flutter ( 7916): #8 _RootZone.runUnaryGuarded (dart:async/zone.dart:1586:10)
E/flutter ( 7916): #9 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:339:11)
E/flutter ( 7916): #10 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
E/flutter ( 7916): #11 _ForwardingStreamSubscription._add (dart:async/stream_pipe.dart:123:11)
E/flutter ( 7916): #12 _MapStream._handleData (dart:async/stream_pipe.dart:218:10)
E/flutter ( 7916): #13 _ForwardingStreamSubscription._handleData (dart:async/stream_pipe.dart:153:13)
E/flutter ( 7916): #14 _RootZone.runUnaryGuarded (dart:async/zone.dart:1586:10)
E/flutter ( 7916): #15 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:339:11)
E/flutter ( 7916): #16 _DelayedData.perform (dart:async/stream_impl.dart:515:14)
E/flutter ( 7916): #17 _PendingEvents.handleNext (dart:async/stream_impl.dart:620:11)
E/flutter ( 7916): #18 _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:591:7)
E/flutter ( 7916): #19 _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
E/flutter ( 7916): #20 _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)
NOTE: I can still do likes even though there are Unhandled Exception and im using firebase as database.
Related
I want to take a screenshot of a widget in a different isolate. Firstly, I tried to take a screenshot in the main thread, and it worked fine but since it's considered a heavy process, I need to do it in a different thread, creating a new isolate. When I tried to take the screenshot via compute I am getting the following error:
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: 'dart:ui/window.dart': Failed assertion: line 298 pos 12: '<optimized out>': is not true.
E/flutter (20904): #0 _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:51:61)
E/flutter (20904): #1 _AssertionError._throwNew (dart:core-patch/errors_patch.dart:40:5)
E/flutter (20904): #2 FlutterWindow.viewConfiguration (dart:ui/window.dart:298:12)
E/flutter (20904): #3 FlutterView.physicalSize (dart:ui/window.dart:136:28)
E/flutter (20904): #4 ScreenshotController.captureFromWidget (package:screenshot/screenshot.dart:123:34)
E/flutter (20904): #5 capture (package:multithreading/components/receipt.dart:12:44)
E/flutter (20904): #6 _IsolateConfiguration.applyAndTime.<anonymous closure> (package:flutter/src/foundation/_isolates_io.dart:108:21)
E/flutter (20904): #7 Timeline.timeSync (dart:developer/timeline.dart:160:22)
E/flutter (20904): #8 _IsolateConfiguration.applyAndTime (package:flutter/src/foundation/_isolates_io.dart:106:21)
E/flutter (20904): #9 _spawn (package:flutter/src/foundation/_isolates_io.dart:127:67)
E/flutter (20904): #10 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:300:17)
E/flutter (20904): #11 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12)
receipt.dart
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:screenshot/screenshot.dart';
final screenshotController = ScreenshotController();
Future<Uint8List> capture(double pixel) async{
final bytes = await screenshotController.captureFromWidget(
Padding(
padding: const EdgeInsets.all(12.0),
child: Container(
height: 500,
width: 300,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20),
decoration: ShapeDecoration(
color: CupertinoColors.systemGreen,
shadows: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
blurRadius: 6,
),
],
),
),
),
delay: Duration.zero,
pixelRatio: pixel,
);
return bytes;
}
computePage.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'components/receipt.dart';
class ComputePage extends StatefulWidget {
const ComputePage({Key? key}) : super(key: key);
#override
State<ComputePage> createState() => _ComputePageState();
}
class _ComputePageState extends State<ComputePage> {
Uint8List? widgetImage;
Future captureWidget() async {
if (widgetImage == null) {
widgetImage = await compute(capture, 10.0);
// widgetImage = await capture(10.0); // Uncomment this line, it works fine
} else {
widgetImage = null;
}
setState(() {});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
height: 500,
width: 300,
alignment: Alignment.center,
decoration: BoxDecoration(
color: widgetImage == null
? const Color(0xFF2AA65C)
: Colors.white,
borderRadius: BorderRadius.circular(30.0),
border: Border.all(color: Colors.red, width: 6),
),
child: widgetImage == null
? const Text(
'Image',
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold,
),
)
: Image.memory(widgetImage!),
),
const SizedBox(height: 50),
ElevatedButton(
onPressed: () {
captureWidget();
},
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFFEAF6EF),
fixedSize: const Size(double.infinity, 50),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0),
),
),
child: const Text(
'Capture',
style: TextStyle(
color: Color(0xFF2AA65C),
fontSize: 16,
fontWeight: FontWeight.w700,
),
),
),
],
),
),
);
}
}
Please copy the code above to reproduce the error
Any help or advice is appreciated....
I working on Flutter mobile App and I'am using GetX as State manager.
I have this exception :
======== Exception caught by widgets library =======================================================
The following assertion was thrown building EmployeesAndCompaniesTab(dirty):
setState() or markNeedsBuild() called during build.
This Obx widget cannot be marked as needing to build because the framework is already in the process of building widgets. A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was: Obx
has builder
dirty
state: _ObxState#14ad0
The widget which was currently being built when the offending call was made was: EmployeesAndCompaniesTab
dirty
The relevant error-causing widget was:
EmployeesAndCompaniesTab EmployeesAndCompaniesTab:file:///search_screen.dart:98:19
When the exception was thrown, this was the stack:
#0 Element.markNeedsBuild.<anonymous closure> (package:flutter/src/widgets/framework.dart:4476:11)
#1 Element.markNeedsBuild (package:flutter/src/widgets/framework.dart:4491:6)
#2 State.setState (package:flutter/src/widgets/framework.dart:1129:15)
#3 _ObxState._updateTree (package:get/get_state_manager/src/rx_flutter/rx_obx_widget.dart:41:7)
#4 GetStream._notifyData (package:get/get_rx/src/rx_stream/get_stream.dart:47:21)
#5 GetStream.add (package:get/get_rx/src/rx_stream/get_stream.dart:97:5)
#6 NotifyManager.addListener.<anonymous closure> (package:get/get_rx/src/rx_types/rx_core/rx_impl.dart:158:40)
#7 GetStream._notifyData (package:get/get_rx/src/rx_stream/get_stream.dart:47:21)
#8 GetStream.add (package:get/get_rx/src/rx_stream/get_stream.dart:97:5)
#9 RxObjectMixin.refresh (package:get/get_rx/src/rx_types/rx_core/rx_impl.dart:29:13)
#10 RxList.length= (package:get/get_rx/src/rx_types/rx_iterables/rx_list.dart:100:5)
#11 ListMixin.clear (dart:collection/list.dart:342:10)
#12 EmployeesAndCompaniesController.onSearch (package:/employees_and_companies_controller.dart:140:49)
#13 EmployeesAndCompaniesTab.build (package:/employees_and_companies_tab.dart:31:16)
#14 _GetCache.build (package:get/get_state_manager/src/simple/get_view.dart:103:20)
#15 GetWidgetCacheElement.build (package:get/get_state_manager/src/simple/get_widget_cache.dart:29:27)
#16 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4806:15)
#17 GetWidgetCacheElement.performRebuild (package:get/get_state_manager/src/simple/get_widget_cache.dart:35:11)
#18 Element.rebuild (package:flutter/src/widgets/framework.dart:4529:5)
#19 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2659:19)
#20 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:891:21)
#21 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:370:5)
#22 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1146:15)
#23 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1083:9)
#24 SchedulerBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/scheduler/binding.dart:864:7)
(elided 4 frames from class _RawReceivePortImpl, class _Timer, and dart:async-patch)
There is my code of Parent Widget who contain Tabs:
class SearchScreen extends GetWidget<SearchController> {
bool isParentReady = true;
#override
Widget build(BuildContext context) {
String workSiteName = "";
SearchScreenArgument passingValue =
ModalRoute
.of(context)!
.settings
.arguments as SearchScreenArgument;
if (passingValue.tabIndex == 1) {
controller.tabController.animateTo(
(controller.tabController.index + passingValue.tabIndex!) % 2);
}
if (passingValue.worksiteName != null) {
workSiteName = passingValue.worksiteName!;
}
return Scaffold(
appBar: AppBar(
title: Text(workSiteName.toString(),
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.left,
style: AppStyle
.textstylecircularstdbold241
.copyWith(
fontSize: getFontSize(24))),
backgroundColor: ColorConstant.indigo600,
),
backgroundColor: ColorConstant.whiteA700,
body: Column(children: [
Expanded(
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(
left: getHorizontalSize(10.00),
top: getVerticalSize(21.00),
right: getHorizontalSize(10.00)),
child: TabBar(
controller: controller.tabController,
labelColor: ColorConstant.indigo600,
unselectedLabelColor: ColorConstant.gray700,
labelPadding: const EdgeInsets.only(left: 10, right: 2),
// TODO decrease height of indicator
indicator: RectangularIndicator(
color: ColorConstant.indigo60033,
bottomRightRadius: 2,
bottomLeftRadius: 2,
topLeftRadius: 2,
topRightRadius: 2,
),
tabs: [
Tab(text: "search".tr),
Tab(text: "control".tr),
],
)),
Expanded(
flex: 1,
child:
TabBarView(controller: controller.tabController, children: [
EmployeesAndCompaniesTab(),
ChecklistScreen(),
]),
)
],
))
]));
}
}
Here is code of the Tab EmployeesAndCompaniesTab(),
class EmployeesAndCompaniesTab
extends GetWidget<EmployeesAndCompaniesController> {
var companies = <Company>[];
String query = '';
EmployeesAndCompaniesTab({Key? key}) : super(key: key);
final EmployeesAndCompaniesController controller =
Get.put(EmployeesAndCompaniesController());
#override
Widget build(BuildContext context) {
controller.onSearch();
final styleActive = TextStyle(color: Colors.black);
final styleHint = TextStyle(color: Colors.black54);
final style = controller.searchController.value.text.isEmpty
? styleHint
: styleActive;
return SingleChildScrollView(
child: Column(
children: [
Align(
alignment: Alignment.center,
child: Padding(
padding: EdgeInsets.only(
left: getHorizontalSize(40.00),
top: getHorizontalSize(10.00),
bottom: getHorizontalSize(20.00)),
child: Center(
child: TabChip(
onCheck: () => controller.onSearch(),
forceDisableCompanyChip:
controller.forceDisableCompanyChip.value),
))),
// search array
Container(
height: 60,
margin: const EdgeInsets.fromLTRB(16, 16, 16, 5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: Colors.white,
border: Border.all(color: Colors.black26),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.5),
spreadRadius: 5,
blurRadius: 7,
offset: Offset(0, 3), // changes position of shadow
),
],
),
padding: const EdgeInsets.symmetric(horizontal: 10),
child: TextField(
controller: controller.searchController,
decoration: InputDecoration(
icon: Icon(Icons.search, color: style.color),
suffixIcon: controller.searchController.value.text.isNotEmpty
? GestureDetector(
child: Icon(Icons.close, color: style.color),
onTap: () {
controller.searchController.clear();
controller.onSearch();
FocusScope.of(context).requestFocus(FocusNode());
},
)
: null,
hintText: "Rechercher",
hintStyle: style,
border: InputBorder.none,
),
style: style,
onChanged: controller.onSearch(),
),
),
// filters
Obx(() => controller.searchedCompanyName.value.isNotEmpty
? Padding(
padding: EdgeInsets.only(
left: getHorizontalSize(15.00),
),
child: Align(
alignment: Alignment.topLeft,
child: InputChip(
onPressed: () {},
onDeleted: () {
controller.onSearch();
controller.searchedCompanyName.value =
""; // TODO remplace "" by Constant.empty
controller.searchedCompanyId = -1;
},
avatar: const Icon(
Icons.filter,
size: 20,
color: Colors.black54,
),
deleteIconColor: Colors.black54,
label: Text("Société : " +
controller.searchedCompanyName.value),
)))
: Text('')),
Obx(() => ListView.builder(
physics: BouncingScrollPhysics(),
shrinkWrap: true,
itemCount:
controller.companyModelObj.value.companyItemList.length,
itemBuilder: (context, index) {
CompanyItemModel model =
controller.companyModelObj.value.companyItemList[index];
return CompanyItemWidget(
model,
onTapTxtAccder: () => onTapCompanyDetailBtn(context, model),
);
})),
// TODO empty text, when nothing
Obx(() => ListView.builder(
physics: BouncingScrollPhysics(),
shrinkWrap: true,
itemCount:
controller.employeeModelObj.value.employeeItemList.length,
itemBuilder: (context, index) {
EmployeeItemModel model =
controller.employeeModelObj.value.employeeItemList[index];
if (controller.employeeModelObj.value.employeeItemList.length <
1 ||
controller.employeeModelObj.value.employeeItemList == null)
return Center(child: Text("Empty"));
return EmployeeItemWidget(
model,
onTapTxtAccder: () => {onTapScanEmployeeBtn(context, model)},
);
}))
],
),
);
}
I'am struggling with this, Help please.
What's the code here search_screen.dart:98:19?
Anyway (as the exception says) this type of error happends when the build method is called while is already building, probably there is a stream or the tabController that triggers the rebuild too early.
am building a drawer menu, the drawer is a stateful class i created called "NavigationDrawer"
and it contains user's name and email. The name and email should be retrieved from the cloud firestore as follow:
import 'package:athaddakapp/model/user_model.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
class NavigationDrawer extends StatefulWidget {
const NavigationDrawer({Key? key}) : super(key: key);
#override
State<NavigationDrawer> createState() => _NavigationDrawerState();
}
class _NavigationDrawerState extends State<NavigationDrawer> {
User? user = FirebaseAuth.instance.currentUser;
UserModel loggedInUser = UserModel();
#override
void initState() {
super.initState();
FirebaseFirestore.instance
.collection("Users")
.doc(user!.uid)
.get()
.then((value) => this.loggedInUser = UserModel.fromMap(value.data()));
setState(() {});
}
#override
Widget build(BuildContext context) {
return Drawer(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
buildHeader(context),
buildMenuItems(context),
],
),
),
);
}
Widget buildHeader(BuildContext context) => Container(
color: Colors.purple,
padding: EdgeInsets.only(
top: MediaQuery.of(context).padding.top,
),
child: Column(
children: [
CircleAvatar(
radius: 52,
backgroundImage: AssetImage("assets/DefaultImage.png"),
),
SizedBox(height: 12),
Text(
"${loggedInUser.name}",
style: TextStyle(fontSize: 20, color: Colors.white),
),
Text("${loggedInUser.email}",
style: TextStyle(fontSize: 17, color: Colors.white)),
SizedBox(
height: 12,
)
],
),
);
Widget buildMenuItems(BuildContext context) => Container(
padding: EdgeInsets.all(20),
child: Wrap(
runSpacing: 14,
children: [
ListTile(
trailing: Icon(Icons.home_outlined),
title: Text(
'الصفحة الرئيسية',
textAlign: TextAlign.right,
),
onTap: () {},
),
ListTile(
trailing: Icon(Icons.flag_outlined),
title: Text(
"تحدياتي",
textAlign: TextAlign.right,
),
onTap: () {},
),
ListTile(
trailing: Icon(Icons.flag_circle_outlined),
title: Text(
'جميع التحديات',
textAlign: TextAlign.right,
),
onTap: () {},
),
ListTile(
trailing: Icon(Icons.settings_outlined),
title: Text(
'إعدادات الحساب',
textAlign: TextAlign.right,
),
onTap: () {},
),
Divider(
color: Colors.purple,
),
ListTile(
trailing: Icon(Icons.question_mark_outlined),
title: Text(
'عن التطبيق',
textAlign: TextAlign.right,
),
onTap: () {},
),
ListTile(
trailing: Icon(Icons.phone_outlined),
title: Text(
'اتصل بنا',
textAlign: TextAlign.right,
),
onTap: () {},
)
],
),
);
}
this navigation class is invoked in other screen called "home_screen", the values are showing as "null" i made sure about the collection name and i restarted the app multiple times but the values still showing as null. i also imported the necessary libraries, here is the firestore database:
when i open the drawer for the first time i logged debugger shows this error:
E/flutter ( 4873): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: NoSuchMethodError: The method '[]' was called on null.
E/flutter ( 4873): Receiver: null
E/flutter ( 4873): Tried calling: []("uid")
E/flutter ( 4873): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:38:5)
E/flutter ( 4873): #1 new UserModel.fromMap
package:athaddakapp/model/user_model.dart:24
E/flutter ( 4873): #2 _NavigationDrawerState.initState.<anonymous closure>
package:athaddakapp/screens/navigation_drawer.dart:26
E/flutter ( 4873): #3 _rootRunUnary (dart:async/zone.dart:1434:47)
E/flutter ( 4873): #4 _CustomZone.runUnary (dart:async/zone.dart:1335:19)
E/flutter ( 4873): <asynchronous suspension>
E/flutter ( 4873):
Move setState to inside of then()... something like:
#override
void initState() {
super.initState();
FirebaseFirestore.instance
.collection("Users")
.doc(user!.uid)
.get()
.then((value) => setState(() => this.loggedInUser = UserModel.fromMap(value.data())));
}
I am trying to make a slider to enlarge and reduce the font but I am facing this error.
E/flutter (11441): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)]
Unhandled Exception: NoSuchMethodError: The method 'setString' was
called on null.
E/flutter (11441): Receiver: null
E/flutter (11441): Tried calling: setString("fontSizeArabic",
"23.99652777777778")
E/flutter (11441): #0 Object.noSuchMethod
(dart:core-patch/object_patch.dart:53:5)
E/flutter (11441): #1 SettingsHelpers.fontSizeArabic
(package:alquranalkareem/helper/settings_helpers.dart:20:17)
E/flutter (11441): #2 _QuranShowState._showTafseer..
(package:alquranalkareem/module/quran/show.dart:881:32)
E/flutter (11441): #3 _SliderState._handleChanged
(package:flutter/src/material/slider.dart:453:14)
E/flutter (11441): #4 _RenderSlider._startInteraction
(package:flutter/src/material/slider.dart:982:7)
E/flutter (11441): #5 _RenderSlider._handleTapDown
(package:flutter/src/material/slider.dart:1031:50)
E/flutter (11441): #6
TapGestureRecognizer.handleTapDown.
(package:flutter/src/gestures/tap.dart:463:51)
E/flutter (11441): #7 GestureRecognizer.invokeCallback
(package:flutter/src/gestures/recognizer.dart:182:24)
E/flutter (11441): #8 TapGestureRecognizer.handleTapDown
(package:flutter/src/gestures/tap.dart:463:11)
E/flutter (11441): #9 BaseTapGestureRecognizer._checkDown
(package:flutter/src/gestures/tap.dart:256:5)
E/flutter (11441): #10 BaseTapGestureRecognizer.didExceedDeadline
(package:flutter/src/gestures/tap.dart:227:5)
E/flutter (11441): #11
PrimaryPointerGestureRecognizer.didExceedDeadlineWithEvent
(package:flutter/src/gestures/recognizer.dart:496:5)
E/flutter (11441): #12
PrimaryPointerGestureRecognizer.addAllowedPointer.
(package:flutter/src/gestures/recognizer.dart:449:40)
E/flutter (11441): #13 _rootRun (dart:async/zone.dart:1122:38)
E/flutter (11441): #14 _CustomZone.run
(dart:async/zone.dart:1023:19)
E/flutter (11441): #15 _CustomZone.runGuarded
(dart:async/zone.dart:925:7)
E/flutter (11441): #16 _CustomZone.bindCallbackGuarded. (dart:async/zone.dart:965:23)
E/flutter (11441): #17 _rootRun (dart:async/zone.dart:1126:13)
E/flutter (11441): #18 _CustomZone.run
(dart:async/zone.dart:1023:19)
E/flutter (11441): #19 _CustomZone.bindCallback. (dart:async/zone.dart:949:23)
E/flutter (11441): #20 Timer._createTimer.
(dart:async-patch/timer_patch.dart:23:15)
E/flutter (11441): #21 _Timer._runTimers
(dart:isolate-patch/timer_impl.dart:384:19)
E/flutter (11441): #22 _Timer._handleMessage
(dart:isolate-patch/timer_impl.dart:418:5)
E/flutter (11441): #23 _RawReceivePortImpl._handleMessage
(dart:isolate-patch/isolate_patch.dart:174:12)
Do you have a solution to the problem?
settings_helpers
import 'dart:convert';
import 'dart:ui';
import 'package:quiver/strings.dart';
import 'package:shared_preferences/shared_preferences.dart';
class SettingsHelpers {
static SettingsHelpers _instance;
static SettingsHelpers get instance {
if (_instance == null) {
_instance = SettingsHelpers();
}
return _instance;
}
SharedPreferences prefs;
Future fontSizeArabic(double fontSize) async {
await prefs.setString('fontSizeArabic', fontSize.toString());
}
static const double minFontSizeArabic = 22;
double get getFontSizeArabic {
String fontSizeString = prefs.getString('fontSizeArabic');
return double.tryParse(fontSizeString ?? minFontSizeArabic.toString());
}
Future setLocale(Locale locale) async {
var map = {
'languageCode': locale.languageCode,
};
var json = jsonEncode(map);
await prefs.setString('locale', json);
}
Locale getLocale() {
var json = prefs.getString('locale');
if (isBlank(json)) {
return Locale('en');
}
var mapJson = jsonDecode(json);
var locale = Locale(mapJson["languageCode"]);
return locale;
}
Future init() async {
prefs = await SharedPreferences.getInstance();
}
}
_showTafseer
Widget _showTafseer(int pageNum) {
TafseerRepository tafseerRepository = new TafseerRepository();
return FutureBuilder<List<Ayat>>(
future: tafseerRepository.getPageTafseer(pageNum),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
List<Ayat> ayat = snapshot.data;
return Padding(
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
children: <Widget>[
Container(
color: Theme.of(context).primaryColorLight,
child: Row(
children: <Widget>[
Slider(
min: SettingsHelpers.minFontSizeArabic,
max: maxFontSizeArabic,
value: fontSizeArabic,
activeColor: Theme.of(context).hoverColor,
inactiveColor: Theme.of(context).primaryColorDark,
onChanged: (double value) async {
await SettingsHelpers.instance
.fontSizeArabic(value);
setState(
() {
fontSizeArabic = value;
},
);
_myEventBus.eventBus.fire(
FontSizeEvent()
..arabicFontSize = value
);
},
),
Container(
decoration: BoxDecoration(
color: Theme.of(context).hoverColor,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(5.0),
topRight: Radius.circular(5.0),
bottomLeft: Radius.circular(5.0),
bottomRight: Radius.circular(5.0),
)
),
alignment: Alignment.center,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Text('${fontSizeArabic.toInt()}',
style: TextStyle(
fontSize: 20,
color: Theme.of(context).primaryColorLight)),
),
),
],
),
),
Container(
// width: 300.0,
height: 500.0,
child: ListView.builder(
itemCount: ayat.length,
itemBuilder: (context, position) {
Ayat aya = ayat[position];
List<String> tafseer = aya.tafsser.split("))");
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
decoration: BoxDecoration(
color: Theme.of(context).backgroundColor,
borderRadius: BorderRadius.only(
topRight: Radius.circular(8.0),
topLeft: Radius.circular(8.0)
)
),
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Text(
"﴿${tafseer.first}﴾",
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: "Uthmanic",
fontWeight: FontWeight.w500,
fontSize: fontSizeArabic
),
),
),
),
Padding(
padding: const EdgeInsets.only(top: 16.0, bottom: 8.0),
child: Text(
"${tafseer.last.trim()}",
textAlign: TextAlign.justify,
style: TextStyle(
color: Theme.of(context).hoverColor,
fontFamily: 'naskh',
fontWeight: FontWeight.w100,
fontSize: fontSizeArabic
),
),
),
Divider()
],
);
}),
),
],
),
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
);
}
I think the issue is with prefs not being properly initialized. Just try making your initialization simpler as below
I have used the factory design pattern. See this article to learn more about it.
Note that I used a simple floating button to trigger the action rather than the slider
class SettingsHelpers {
SharedPreferences prefs;
static final SettingsHelpers _instance = SettingsHelpers._internal();
SettingsHelpers._internal(){
_init();
}
factory SettingsHelpers() => _instance;
void _init() async {
prefs = await SharedPreferences.getInstance();
}
void fontSizeArabic(double fontSize) async {
prefs.setString('fontSizeArabic', fontSize.toString());
}
static const double minFontSizeArabic = 22;
double get getFontSizeArabic {
String fontSizeString = prefs.getString('fontSizeArabic');
return double.tryParse(fontSizeString ?? minFontSizeArabic.toString());
}
Future setLocale(Locale locale) async {
var map = {
'languageCode': locale.languageCode,
};
var json = jsonEncode(map);
await prefs.setString('locale', json);
}
Locale getLocale() {
var json = prefs.getString('locale');
if (isBlank(json)) {
return Locale('en');
}
var mapJson = jsonDecode(json);
var locale = Locale(mapJson["languageCode"]);
return locale;
}
}
class SampleTest extends StatefulWidget {
#override
_SampleTestState createState() => _SampleTestState();
}
class _SampleTestState extends State<SampleTest> {
double fontSizeArabic;
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton:
FloatingActionButton(child: Icon(Icons.add), onPressed: _onPressed),
);
}
void _onPressed() async {
double value = 18.0;
SettingsHelpers().fontSizeArabic(value);
}
}
I have an article search feature on my application by implementing BLOC and RX Dart. I have succeeded in searching the article based on the "title" that became the key in the search, but when I filled in the "title" incorrectly, the results did not issue an error such as "Article does not exist / anything else" and the results were not real-time according to the key " title "is meant and instead gets an error in LogCat as below:
E/flutter (25135): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: NoSuchMethodError: Class 'String' has no instance method 'forEach'.
E/flutter (25135): Receiver: "Data not found"
E/flutter (25135): Tried calling: forEach(Closure: (dynamic) => Null)
E/flutter (25135): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:50:5)
E/flutter (25135): #1 new Articles.fromJson (package:vallery/src/models/articles/articles.dart:11:22)
E/flutter (25135): #2 ApiProvider.searchArticle (package:vallery/src/resources/api/api_provider.dart:65:23)
E/flutter (25135): <asynchronous suspension>
E/flutter (25135): #3 Repository.searchArticlesRepository (package:vallery/src/resources/repository/repository.dart:19:74)
E/flutter (25135): #4 SearchArticleBloc.searchArticleBloc (package:vallery/src/blocs/article/articles_search_bloc.dart:12:42)
E/flutter (25135): <asynchronous suspension>
E/flutter (25135): #5 EditableTextState._formatAndSetValue (package:flutter/src/widgets/editable_text.dart:1335:14)
E/flutter (25135): #6 EditableTextState.updateEditingValue (package:flutter/src/widgets/editable_text.dart:971:5)
E/flutter (25135): #7 _TextInputClientHandler._handleTextInputInvocation (package:flutter/src/services/text_input.dart:743:36)
E/flutter (25135): <asynchronous suspension>
E/flutter (25135): #8 MethodChannel._handleAsMethodCall (package:flutter/src/services/platform_channel.dart:397:55)
E/flutter (25135): <asynchronous suspension>
E/flutter (25135): #9 MethodChannel.setMethodCallHandler.<anonymous closure> (package:flutter/src/services/platform_channel.dart:365:54)
E/flutter (25135): #10 _DefaultBinaryMessenger.handlePlatformMessage (package:flutter/src/services/binary_messenger.dart:110:33)
E/flutter (25135): <asynchronous suspension>
E/flutter (25135): #11 _invoke3.<anonymous closure> (dart:ui/hooks.dart:280:15)
E/flutter (25135): #12 _rootRun (dart:async/zone.dart:1124:13)
E/flutter (25135): #13 _CustomZone.run (dart:async/zone.dart:1021:19)
E/flutter (25135): #14 _CustomZone.runGuarded (dart:async/zone.dart:923:7)
E/flutter (25135): #15 _invoke3 (dart:ui/hooks.dart:279:10)
E/flutter (25135): #16 _dispatchPlatformMessage (dart:ui/hooks.dart:141:5)
This is the model:
class Articles {
int status;
List<Result> result;
Articles({this.status, this.result});
Articles.fromJson(Map<String, dynamic> json) {
status = json['status'];
if (json['result'] != null) {
result = new List<Result>();
json['result'].forEach((v) {
result.add(new Result.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['status'] = this.status;
if (this.result != null) {
data['result'] = this.result.map((v) => v.toJson()).toList();
}
return data;
}
}
class Result {
String idArtikel;
String title;
String sinopsis;
String content;
String createdDate;
String thumbnail;
Result(
{this.idArtikel,
this.title,
this.sinopsis,
this.content,
this.createdDate,
this.thumbnail});
Result.fromJson(Map<String, dynamic> json) {
idArtikel = json['id_artikel'];
title = json['title'];
sinopsis = json['sinopsis'];
content = json['content'];
createdDate = json['created_date'];
thumbnail = json['thumbnail'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id_artikel'] = this.idArtikel;
data['title'] = this.title;
data['sinopsis'] = this.sinopsis;
data['content'] = this.content;
data['created_date'] = this.createdDate;
data['thumbnail'] = this.thumbnail;
return data;
}
}
This is the API:
class ApiProvider {
Client client = Client();
static final String baseUrl = 'link_api';
Future<Articles> searchArticle(String title) async {
final response = await client.post(baseUrl + 'search-artikel', body: {
"title" : title
});
if (response.statusCode == 200) {
return Articles.fromJson(json.decode(response.body));
} else {
throw Exception('Gagal ambil data article');
}
}
}
This is the repository:
class Repository {
final apiProvider = ApiProvider();
Future<Articles> searchArticlesRepository(String title) => apiProvider.searchArticle(title);
}
This is the BLoC:
class SearchArticleBloc {
final repository = Repository();
final articleSearchFetcher = PublishSubject<Articles>();
Observable<Articles> get allSearchArticle => articleSearchFetcher.stream;
searchArticleBloc(String title) async {
Articles articles = await repository.searchArticlesRepository(title);
articleSearchFetcher.sink.add(articles);
}
dispose() {
articleSearchFetcher.close();
}
}
And this is the UI:
class SearchArticlePage extends StatefulWidget {
#override
_SearchArticlePageState createState() => _SearchArticlePageState();
}
class _SearchArticlePageState extends State<SearchArticlePage> {
final blocSearchArticle = SearchArticleBloc();
#override
void dispose() {
blocSearchArticle.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: color_white,
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
backgroundColor: color_white,
iconTheme: IconThemeData(
color: color_blue_bg, //change your color here
),
centerTitle: true,
floating: true,
pinned: true,
title: TextField(
autofocus: true,
style: TextStyle(fontSize: 17, color: color_blue_bg),
decoration: InputDecoration.collapsed(
hintText: "Article Name...",
hintStyle: TextStyle(fontSize: 17, color: color_blue_bg),
),
onChanged: blocSearchArticle.searchArticleBloc,
),
)
];
},
body: getListResult(),
),
);
}
Widget getListResult() {
return StreamBuilder(
stream: blocSearchArticle.allSearchArticle,
builder: (BuildContext context, AsyncSnapshot<Articles> snapshot) {
if(snapshot.hasData) {
return showListResult(snapshot);
} else if (!snapshot.hasData) {
return Center(
child: Text('Data not found'),
);
} else if(snapshot.hasError) {
return Text(snapshot.error.toString());
}
return Center(
child: CircularProgressIndicator(),
);
},
);
}
Widget showListResult(AsyncSnapshot<Articles> snapshot) {
return Container(
margin: EdgeInsets.only(top: 10.0),
child: ListView.builder(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
scrollDirection: Axis.vertical,
itemCount: snapshot.data.result == null ? Center(child: Text('Data not found')) : snapshot?.data?.result?.length ?? 0,
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
child: Container(
height: MediaQuery.of(context).size.height / 7.0,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
child: Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Container(
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
child: FadeInImage.assetNetwork(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width / 3,
placeholder: 'assets/images/img_default_bg.png',
image: '${snapshot.data.result[0].thumbnail}',
fit: BoxFit.cover,
),
),
),
Expanded(
child: Container(
margin: EdgeInsets.only(
left: MediaQuery.of(context).size.width / 41,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.only(
right: MediaQuery.of(context).size.width/41,
bottom: MediaQuery.of(context).size.width/ 80,
),
child: Text(
snapshot.data.result[index].title,
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(
color: Colors.black,
fontSize: MediaQuery.of(context).size.width / 25,
fontWeight: FontWeight.bold,
),
),
),
Padding(
padding: EdgeInsets.only(
right: MediaQuery.of(context).size.width/41,
bottom: MediaQuery.of(context).size.width/ 80,
),
child: Text(
snapshot.data.result[index].sinopsis,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Colors.black,
fontSize: MediaQuery.of(context).size.width / 35,
fontWeight: FontWeight.normal,
),
),
),
SizedBox(height: MediaQuery.of(context).size.height / 50,
),
Padding(
padding: EdgeInsets.only(
right: MediaQuery.of(context).size.width/41,
bottom: MediaQuery.of(context).size.width/ 80,
),
child: Text(
snapshot.data.result[index].createdDate,
style: TextStyle(
color: Colors.black,
fontSize: MediaQuery.of(context).size.width / 35,
fontWeight: FontWeight.normal,
),
),
),
],
),
),
),
],
),
),
),
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context){
return ArticleDetailPage(
id: snapshot.data.result[index].idArtikel,
title: snapshot.data.result[index].title,
thumbnail: '${snapshot.data.result[index].thumbnail}',
);
}),
);
},
);
},
),
);
}
}
Can someone help me? Because I was dizzy to find a solution to this error :)
The problem is here:
if (json['result'] != null) {
result = new List<Result>();
json['result'].forEach((v) {
result.add(new Result.fromJson(v));
});
}
You are expecting the "result" part of the JSON to be a list, but it's apparently a string. Check the actual JSON text and you will probably find "result": "some result", not "result": [ ... Consider editing the question to show the actual JSON.
As an aside there's a simpler syntax to do what you are doing in the snippet above. (Naturally that will give the same error until you solve the JSON array vs string problem.)
result = json['result'].map<Result>((j) => Result.fromJson(j).toList();
Solve this problem if (json['result'] != '' && json['result'] != null) { result = new List<Result>(); json['result'].forEach((v) { result.add(new Result.fromJson(v));});}