如何在不创建新的窗口小部件分支的情况下重用相同的布局屏幕 [英] How to reuse the same layout screen without creating a new widget tree branch

查看:48
本文介绍了如何在不创建新的窗口小部件分支的情况下重用相同的布局屏幕的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发Flutter Web应用程序.

I am developing Flutter Web Application.

目标是将大多数布局屏幕的相同布局屏幕小部件(Drawer,AppBar)重用.

The object is to reuse the same layout screen widget(Drawer, AppBar) for most of route screen.

我尝试创建一个新的Scaffold类,并将body小部件添加到每个屏幕.

I have tried create a new Scaffold class and add body widget to each screen.

问题是每次我导航到新屏幕时.在小部件树上创建了一个新的(MyScaffold).因此对性能不利.

The problem is every time I navigate to a new screen. There is a new (MyScaffold) created on the widget tree. So it is not good for performance.

我也尝试使用嵌套路由器,问题是URL不支持嵌套路由器,我无法通过键入URL导航到屏幕.

I also tried to use nested router, the problem is nested router is not supported by url that I can not navigate to the screen by typing the URL.

还有其他适当的方法来解决此问题.

Is there any other proper way to deal with this problem.

谢谢

添加代码示例:

import 'package:flutter/material.dart';

void main() => runApp(AppWidget());

class AppWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: '/',
      routes: {
        '/': (context) => FirstScreen(),
        '/second': (context) => SecondScreen(),
      },
    );
  }
}

class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Screen'),
      ),
      body: Center(
        child: RaisedButton(
          child: Text('Launch screen'),
          onPressed: () {
            Navigator.pushReplacementNamed(context, '/second');
          },
        ),
      ),
    );
  }
}

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Screen"),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            Navigator.pushReplacementNamed(context, '/');
          },
          child: Text('Go back!'),
        ),
      ),
    );
  }
}

我将尝试更好地解释这个问题.

And I will try to explain the question better.

如您所见, 第一屏 第二屏 具有完全相同的小部件树结构.但是每当出现问题时,都要删除屏幕小部件"并创建一个新的小部件.

As you can see First Screen and Second Screen has Exactly same structure of widget tree. But every time flutter is remove the Screen Widget and create a new one.

我还尝试更改代码以创建新的 MyScaffold 并重用相同的Widget类:

I also tried to change the code to create a new MyScaffold and reuse the same Widget class :

class AppWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: '/',
      routes: {
        '/': (context) => MyScallfold(
              bodyWidget: FirstScreen(),
            ),
        '/second': (context) => MyScallfold(
              bodyWidget: SecondScreen(),
            ),
      },
    );
  }
}

class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      onPressed: () {
        Navigator.pushReplacementNamed(context, '/second');
      },
      child: Text('To Screen 2!'),
    );
  }
}

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      onPressed: () {
        Navigator.pushReplacementNamed(context, '/');
      },
      child: Text('To Screen 1!'),
    );
  }
}

class MyScallfold extends StatelessWidget {
  Widget bodyWidget;
  MyScallfold({this.bodyWidget});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('WebAppTest'),
      ),
      body: bodyWidget,
    );
  }
}

我每次使用导航时都注意到公交车,树的所有小部件都被重建(renderObject #id已更改)

Bus I noticed every time I use the navigation, all the widget of the tree is rebuilt (The renderObject #id is changed)

那么是否可以在Flutter中重用相同的RenderObject(AppBar,RichText)来优化性能?

So is it possible to reuse the same RenderObject (AppBar, RichText) in flutter to optimise the performance ?

推荐答案

快速答案是否",无论如何还没有.当前,当您使用Navigator时,它会刷新页面并重建完整视图.

The quick answer is no, not yet anyway. Currently when you use Navigator it refreshes the page and rebuilds the full view.

当前Flutter网站上最有效的方法是使用 TabController 在具有状态的窗口小部件中使用 TabBarView ="https://api.flutter.dev/flutter/widgets/SingleTickerProviderStateMixin-mixin.html" rel ="nofollow noreferrer"> SingleTickerProviderStateMixin .

The most efficient way on Flutter web currently would be to use a TabController with a TabBarView in a Stateful widget with SingleTickerProviderStateMixin.

它仅加载屏幕上的窗口小部件,而不需要重新加载页面即可查看其他页面.您的示例如下所示(我已经添加了动画以过渡到下一页,但是您可以将其删除):

It only loads what Widget is on screen, but doesn't require the page to reload to view other pages. Your example would look like this (I have added animation to transition to the next page, but you can remove it):

import 'package:flutter/material.dart';

TabController tabController;

class MainScreen extends StatefulWidget {
  @override
  _MainScreenState createState() => _MainScreenState();
}

class _MainScreenState extends State<MainScreen> with SingleTickerProviderStateMixin {
  int activeTab = 0;
  @override
  void initState() {
    tabController = TabController(length: 3, vsync: this, initialIndex: 0)
      ..addListener(() {
        setState(() {
          activeTab = tabController.index;
        });
      });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('WebAppTest'),
      ),
      body: Expanded(
        child: TabBarView(
          controller: tabController,
          children: <Widget>[
            FirstScreen(), //Index 0
            SecondScreen(), //Index 1
            ThirdScreen(), //Index 2
          ],
        ),
      ),
    );
  }
}

class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      onPressed: () {
        tabController.animateTo(2);
      },
      child: Text('To Screen 3!'),
    );
  }
}

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      onPressed: () {
        tabController.animateTo(0);
      },
      child: Text('To Screen 1!'),
    );
  }
}

class ThirdScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      onPressed: () {
        tabController.animateTo(1);
      },
      child: Text('To Screen 2!'),
    );
  }
}

这篇关于如何在不创建新的窗口小部件分支的情况下重用相同的布局屏幕的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆