I have built a Flutter application using MobX as my state management and am running into a strange issue at the moment that is only present on Android running in release mode.
I'm not sure if the offender is MobX, Hive or just Flutter in Android itself. However, on this specific page in my app, the Obsever will only display the last entry in the list. The other items are present, but the UI will only show the last index of the list. When I turn my phone landscape, the full content of the list is then visible and the page displays exactly as intended. Is there a way I can force the widgets to re-render in MobX when the page has already loaded?
I have tried downgrading my target SDK to 28, downgrading the gradle version, setting shrinkResources & minifyEnabled to false, enabled proguard. I also have ensured to call this in my main.dart;
WidgetsFlutterBinding.ensureInitialized();
Also attached are the outputs of my flutter doctor.
Again, this issue is only present on Android release build of my app. It works perfectly on iOS & Android on debug.
Any help would be greatly appreciated.
Below is the widget in question that has issues rendering in release mode
Widget _carPackageList() {
return ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: viewModel.customerCars.length,
itemBuilder: (context, index) => _carListItem(index));
}
Widget _carListItem(index) {
var packageDetails = viewModel.getDetailBookingById(
viewModel.customerCars[index].packageGroupId);
return Observer(
builder: (context) {
if (viewModel.isLoading) {
return CustomProgressIndiactor();
} else {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: Column(
children: [
Text(
viewModel.customerCars[index].makeAndModel,
maxLines: 2,
style: TextStyle(
fontSize: 25,
fontFamily: 'Domus',
color: Color(0xff3c99a0))),
],
),
),
IconButton(
icon: Icon(Icons.highlight_remove, color: Colors.black),
onPressed: () {
viewModel.removeCustomerCar(index);
viewModel.customerCars.removeAt(index);
})
],
),
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
child: Container(
width: double.infinity,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(15.0),
child: Text(packageDetails.name,
overflow: TextOverflow.ellipsis,
maxLines: 2,
style: TextStyle(
fontSize: 25,
fontFamily: 'Domus',
color: Color(0xff3c99a0))),
),
],
),
),
Padding(
padding: const EdgeInsets.all(15.0),
child: Observer(
builder: (_) {
var groupPrice =
viewModel.calculateCarCost(
viewModel.customerCars[index],
viewModel.customerCars[index]
.packageGroupId);
if (groupPrice == null) {
return Text('£0.00',
style: TextStyle(
color: Color(0xff1A2E35),
fontFamily: 'Aileron',
fontWeight: FontWeight.w700));
} else {
return Text(
'£${groupPrice.toStringAsFixed(2)}',
style: TextStyle(
color: Color(0xff1A2E35),
fontFamily: 'Aileron',
fontWeight: FontWeight.w700),
);
}
},
),
),
],
),
Padding(
padding: const EdgeInsets.only(
left: 15.0, top: 0, right: 15),
child: Text(packageDetails.description,
style: TextStyle(
color: Color(0xff1A2E35),
fontFamily: 'Aileron',
fontSize: 16,
fontWeight: FontWeight.w300)),
),
Padding(
padding: const EdgeInsets.all(15.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Optional Extras',
style: GoogleFonts.lato(
fontSize: 16,
color: Colors.black,
fontWeight: FontWeight.bold)),
Observer(
builder: (_) {
var opExtraPrice = viewModel
.calculateOptionalExtrasPrice(viewModel
.customerCars[index]
.optionalExtras);
if (opExtraPrice == null) {
return Text('£0.00',
style: TextStyle(
color: Color(0xff1A2E35),
fontFamily: 'Aileron',
fontWeight: FontWeight.w700));
} else {
return Text(
'£${opExtraPrice.toStringAsFixed(2)}',
style: TextStyle(
color: Color(0xff1A2E35),
fontFamily: 'Aileron',
fontWeight: FontWeight.w700));
}
},
),
],
),
),
Padding(
padding: const EdgeInsets.all(15.0),
child: ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: viewModel.customerCars[index]
.optionalExtras.length,
itemBuilder: (context, innerIndex) {
var detailedOptionalExtra =
viewModel.getOptinalExtraById(viewModel
.customerCars[index]
.optionalExtras[innerIndex]
.packageItemId);
return Text(
detailedOptionalExtra.name,
style: TextStyle(
color: Color(0xff1A2E35),
fontFamily: 'Aileron',
fontSize: 16,
fontWeight: FontWeight.w300),
);
},
)),
Padding(
padding: const EdgeInsets.all(15.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'Total Cost:',
style: TextStyle(
color: Color(0xff1A2E35),
fontFamily: 'Aileron',
fontSize: 16,
fontWeight: FontWeight.w700),
),
Observer(
builder: (context) => Text(
'£${viewModel.currentTotalCost.toStringAsFixed(2)}',
style: TextStyle(
color: Color(0xff1A2E35),
fontFamily: 'Aileron',
fontWeight: FontWeight.w700))),
],
),
)
],
),
),
),
],
),
);
}
},
);
}