TabBarView displays properly with Flutter debug but not with release

Viewed 68

TabBarView displays properly with Flutter debug but not with release

Windows11 / Flutter 3.0.1 / Getx 4.6.5

flutter run --release output:

I/flutter (31177): Null check operator used on a null value
I/flutter (31177): #0      _PagePosition.applyViewportDimension (package:flutter/src/widgets/page_view.dart:455)
I/flutter (31177): #1      RenderViewport.performLayout (package:flutter/src/rendering/viewport.dart:1456)
I/flutter (31177): #2      RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #3      RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #4      RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #5      RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #6      RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #7      RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #8      RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #9      RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #10     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #11     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #12     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #13     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #14     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #15     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #16     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #17     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #18     RenderCustomPaint.performLayout (package:flutter/src/rendering/custom_paint.dart:545)
I/flutter (31177): #19     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #20     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #21     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #22     MultiChildLayoutDelegate.layoutChild (package:flutter/src/rendering/custom_layout.dart:171)
I/flutter (31177): #23     _ScaffoldLayout.performLayout (package:flutter/src/material/scaffold.dart:1003)
I/flutter (31177): #24     MultiChildLayoutDelegate._callPerformLayout (package:flutter/src/rendering/custom_layout.dart:240)
I/flutter (31177): #25     RenderCustomMultiChildLayoutBox.performLayout (package:flutter/src/rendering/custom_layout.dart:403)
I/flutter (31177): #26     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #27     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #28     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #29     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #30     _RenderCustomClip.performLayout (package:flutter/src/rendering/proxy_box.dart:1376)
I/flutter (31177): #31     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #32     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #33     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #34     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #35     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #36     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #37     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #38     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #39     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #40     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #41     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #42     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #43     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #44     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #45     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #46     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #47     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #48     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #49     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #50     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #51     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #52     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #53     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #54     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #55     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #56     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #57     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #58     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #59     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #60     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #61     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #62     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #63     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #64     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #65     RenderOffstage.performLayout (package:flutter/src/rendering/proxy_box.dart:3462)
I/flutter (31177): #66     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #67     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #68     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #69     _RenderTheatre.performLayout (package:flutter/src/widgets/overlay.dart:749)
I/flutter (31177): #70     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #71     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #72     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #73     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #74     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #75     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #76     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #77     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #78     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #79     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #80     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #81     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #82     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #83     RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116)
I/flutter (31177): #84     RenderObject.layout (package:flutter/src/rendering/object.dart:1915)
I/flutter (31177): #85     RenderView.performLayout (package:flutter/src/rendering/view.dart:165)
I/flutter (31177): #86     RenderObject._layoutWithoutResize (package:flutter/src/rendering/object.dart:1757)
I/flutter (31177): #87     PipelineOwner.flushLayout (package:flutter/src/rendering/object.dart:887)
I/flutter (31177): #88     RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:504)
I/flutter (31177): #89     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:892)
I/flutter (31177): #90     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:370)
I/flutter (31177): #91     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1146)
I/flutter (31177): #92     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1083)
I/flutter (31177): #93     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:997)
I/flutter (31177): #97     _invoke (dart:ui/hooks.dart:151)
I/flutter (31177): #98     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:308)
I/flutter (31177): #99     _drawFrame (dart:ui/hooks.dart:115)
I/flutter (31177): (elided 3 frames from dart:async)

main.dart

import 'package:get/get.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      initialRoute: RouteConfig.home,
      getPages: RouteConfig.getPages,
    );
  }
}

class RouteConfig {
  static const String home = "/home";
  static final List<GetPage> getPages = [
    GetPage(
      name: home,
      page: () => const HomePage(),
      binding: HomeBinding(),
    )
  ];
}

//----------------------------------------------------home------------------------------------

class HomeBinding extends Bindings {
  @override
  void dependencies() {
    Get.lazyPut(() => HomeController());
  }
}

class HomeController extends GetxController
    with GetSingleTickerProviderStateMixin {
  final List<Tab> tabs = <Tab>[const Tab(text: 'Movie'), const Tab(text: 'Tv')];

  late TabController tabController;

  @override
  void onInit() {
    debugPrint("HomeController onInit");
    super.onInit();
    tabController = TabController(vsync: this, length: tabs.length);
    tabController.addListener(() {
      debugPrint(
          "TabController listen, index:${tabController.index}, len:${tabController.length}");
    });
  }

  @override
  void onClose() {
    debugPrint("HomeController onClose");
    tabController.dispose();
    super.onClose();
  }
}

class HomePage extends GetView<HomeController> {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GetBuilder<HomeController>(
      builder: (logic) {
        return Scaffold(
          appBar: AppBar(
            leading: const Icon(
              Icons.home,
            ),
            title: const Text('Home'),
            centerTitle: true,
            actions: [
              IconButton(
                icon: const Icon(Icons.search),
                color: Colors.white,
                onPressed: () {
                  debugPrint("search");
                },
              ),
            ],
            bottom: TabBar(
              isScrollable: true,
              indicatorWeight: 1,
              indicatorSize: TabBarIndicatorSize.tab,
              indicatorColor: Colors.white,
              controller: logic.tabController,
              tabs: logic.tabs,
              onTap: (index) {
                debugPrint("TabBar index: $index");
              },
            ),
          ),
          body: TabBarView(
            controller: logic.tabController,
            children: logic.tabs.map((tab) {
              debugPrint("create TabBarView, tab:${tab.text}");
              if (tab.text == null) {
                return const Center(child: Text("default"));
              }
              if (tab.text == "Movie") {
                return const StatefulMoviePage();
              }
              return Center(child: Text(tab.text!));
            }).toList(),
          ),
        );
      },
    );
  }
}

//----------------------------------------------------movie------------------------------------

class Movie {
  int id = 0;
  String name = "";
  String image = "";
  Movie(this.id, this.name, this.image);
}

class MovieState {
  late List<Movie> movies;

  MovieState() {
    movies = <Movie>[];
  }
}

class MovieController extends GetxController {
  final state = MovieState();

  @override
  void onInit() {
    debugPrint("MovieController onInit");
    super.onInit();
    state.movies = <Movie>[
      Movie(1, "movie1", "/files/1"),
      Movie(2, "movie2", "/files/1"),
      Movie(3, "movie3", "/files/1"),
    ];
  }
}

class StatefulMoviePage extends StatefulWidget {
  const StatefulMoviePage({Key? key}) : super(key: key);

  @override
  StatefulMoviePageState createState() => StatefulMoviePageState();
}

class StatefulMoviePageState extends State<StatefulMoviePage>
    with AutomaticKeepAliveClientMixin {
  @override
  Widget build(BuildContext context) {
    debugPrint("StatefulMoviePageState build start");
    super.build(context);
    return const MoviePage();
  }

  @override
  bool get wantKeepAlive => true;
}

class MoviePage extends GetView<MovieController> {
  const MoviePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    debugPrint("MoviePage build start");

    Get.put(MovieController());

    return GetBuilder<MovieController>(
      builder: (c) {
        debugPrint("movies: ${c.state.movies.length}");
        return ListView(
          children: c.state.movies.map((Movie m) {
            return ListTile(title: Text(m.name));
          }).toList(),
        );
      },
    );
  }
}

1 Answers

tldr: add a delay to give tabbar view time to Initialise, add async to main with await Future.delayed(const Duration(milliseconds: XXX));

I also had this issue when running in release mode, (worked fine in debug). It seems the problem is the widget is not properly initialized, so you have to wait or give some delay when you run your app in the main() function

Maybe this would help:

Instead of this:

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  NotificationService().initNotification();
  runApp(const MainPage());
}

You can have:

void main() async{
  WidgetsFlutterBinding.ensureInitialized();
  NotificationService().initNotification();
  await Future.delayed(const Duration(milliseconds: 300));
  runApp(const MainPage());
}
Related