Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter 从类型名称动态创建实例_Flutter_Dart_Createinstance - Fatal编程技术网

Flutter 从类型名称动态创建实例

Flutter 从类型名称动态创建实例,flutter,dart,createinstance,Flutter,Dart,Createinstance,有一个问题——如果我有一个包含其名称的字符串变量,我是否可以创建类实例 例如,我有 var className = 'DocumentsList'; 我可以这样做吗 var docListWidget = createInstance(className[, params]); 颤振(和飞镖)没有这样做的设施。故意地他们实现了树摇动,一种删除未使用代码的机制,使你的应用程序更小更快。然而,要做到这一点,编译器必须知道使用了什么代码,没有使用什么代码。如果你能像你描述的那样做,它就不可能知道使

有一个问题——如果我有一个包含其名称的字符串变量,我是否可以创建类实例

例如,我有

var className = 'DocumentsList';
我可以这样做吗

var docListWidget = createInstance(className[, params]);
颤振(和飞镖)没有这样做的设施。故意地他们实现了树摇动,一种删除未使用代码的机制,使你的应用程序更小更快。然而,要做到这一点,编译器必须知道使用了什么代码,没有使用什么代码。如果你能像你描述的那样做,它就不可能知道使用了什么代码

所以不,这是不可能的。没有那样的自由度。您可以使用一个大的switch语句来创建基于字符串的类,前提是您事先知道它将是哪个字符串。这是静态的,编译器可以使用它

您需要的是“反射”,您可以使用诸如或之类的包添加一些功能,但它们不能更改编译过程,它们也可以通过您事先指定哪些类需要反射来工作。完全动态的使用是不可能的(故意的)


因为您提到了路由表:您不能从字符串创建类,但是您可以从类创建字符串:

import 'package:flutter/material.dart';

typedef Builder<T> = T Function(BuildContext context);

String routeName<T extends Widget>() {
  return T.toString().toLowerCase();
}

MapEntry<String, Builder<Widget>> createRouteWithName<T extends Widget>(Builder<T> builder) {
    return new MapEntry(routeName<T>(), (context) => builder(context));
}

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: routeName<ScreenPicker>(),
      routes: Map.fromEntries([
        createRouteWithName((context) => ScreenPicker()),
        createRouteWithName((context) => ScreenOne()),
        createRouteWithName((context) => ScreenTwo()),
      ]),
    );
  }
}

class ScreenPicker extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(appBar: AppBar(title: Text("Navigate a route")), 
                    body: Column(children: [
                      RaisedButton(
                        child: Text('One'),
                        onPressed: () => Navigator.pushNamed(context, routeName<ScreenOne>())),
                      RaisedButton(
                        child: Text('Two'),
                        onPressed: () => Navigator.pushNamed(context, routeName<ScreenTwo>())),
                    ]));
  }
}

class ScreenTwo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(appBar: AppBar(title: Text("Second Screen")), body: Center(child: Text("Two")));
  }
}

class ScreenOne extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(appBar: AppBar(title: Text("First Screen")), body: Center(child: Text("One")));
  }
}
导入“包装:颤振/材料.省道”;
typedef Builder=T函数(BuildContext上下文);
字符串routeName(){
返回T.toString().toLowerCase();
}
MapEntry createRouteWithName(生成器){
返回新的映射条目(routeName(),(context)=>builder(context));
}
void main(){
runApp(MyApp());
}
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
initialRoute:routeName(),
路线:Map.fromEntries([
createRouteWithName((上下文)=>ScreenPicker()),
createRouteWithName((上下文)=>ScreenOne()),
createRouteWithName((上下文)=>ScreenTwo()),
]),
);
}
}
类ScreenPicker扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回脚手架(appBar:appBar(标题:文本(“导航路线”)),
正文:列(子项:[
升起的按钮(
子项:文本(“一”),
onPressed:()=>Navigator.pushNamed(上下文,routeName()),
升起的按钮(
child:Text('Two'),
onPressed:()=>Navigator.pushNamed(上下文,routeName()),
]));
}
}
类ScreenTwo扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回脚手架(appBar:appBar(标题:文本(“第二个屏幕”)),主体:中间(子项:文本(“两个”));
}
}
类ScreenOne扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回脚手架(appBar:appBar(标题:文本(“第一屏”)),主体:中心(子:文本(“一”)));
}
}
这样,您的项目中就不会有带有路由名称的字符串,这些字符串在重命名某些内容时可能会被更改、键入错误或忘记。

flatter(和Dart)没有这样做的功能。故意地他们实现了树摇动,一种删除未使用代码的机制,使你的应用程序更小更快。然而,要做到这一点,编译器必须知道使用了什么代码,没有使用什么代码。如果你能像你描述的那样做,它就不可能知道使用了什么代码

所以不,这是不可能的。没有那样的自由度。您可以使用一个大的switch语句来创建基于字符串的类,前提是您事先知道它将是哪个字符串。这是静态的,编译器可以使用它

您需要的是“反射”,您可以使用诸如或之类的包添加一些功能,但它们不能更改编译过程,它们也可以通过您事先指定哪些类需要反射来工作。完全动态的使用是不可能的(故意的)


因为您提到了路由表:您不能从字符串创建类,但是您可以从类创建字符串:

import 'package:flutter/material.dart';

typedef Builder<T> = T Function(BuildContext context);

String routeName<T extends Widget>() {
  return T.toString().toLowerCase();
}

MapEntry<String, Builder<Widget>> createRouteWithName<T extends Widget>(Builder<T> builder) {
    return new MapEntry(routeName<T>(), (context) => builder(context));
}

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: routeName<ScreenPicker>(),
      routes: Map.fromEntries([
        createRouteWithName((context) => ScreenPicker()),
        createRouteWithName((context) => ScreenOne()),
        createRouteWithName((context) => ScreenTwo()),
      ]),
    );
  }
}

class ScreenPicker extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(appBar: AppBar(title: Text("Navigate a route")), 
                    body: Column(children: [
                      RaisedButton(
                        child: Text('One'),
                        onPressed: () => Navigator.pushNamed(context, routeName<ScreenOne>())),
                      RaisedButton(
                        child: Text('Two'),
                        onPressed: () => Navigator.pushNamed(context, routeName<ScreenTwo>())),
                    ]));
  }
}

class ScreenTwo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(appBar: AppBar(title: Text("Second Screen")), body: Center(child: Text("Two")));
  }
}

class ScreenOne extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(appBar: AppBar(title: Text("First Screen")), body: Center(child: Text("One")));
  }
}
导入“包装:颤振/材料.省道”;
typedef Builder=T函数(BuildContext上下文);
字符串routeName(){
返回T.toString().toLowerCase();
}
MapEntry createRouteWithName(生成器){
返回新的映射条目(routeName(),(context)=>builder(context));
}
void main(){
runApp(MyApp());
}
类MyApp扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回材料PP(
initialRoute:routeName(),
路线:Map.fromEntries([
createRouteWithName((上下文)=>ScreenPicker()),
createRouteWithName((上下文)=>ScreenOne()),
createRouteWithName((上下文)=>ScreenTwo()),
]),
);
}
}
类ScreenPicker扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回脚手架(appBar:appBar(标题:文本(“导航路线”)),
正文:列(子项:[
升起的按钮(
子项:文本(“一”),
onPressed:()=>Navigator.pushNamed(上下文,routeName()),
升起的按钮(
child:Text('Two'),
onPressed:()=>Navigator.pushNamed(上下文,routeName()),
]));
}
}
类ScreenTwo扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回脚手架(appBar:appBar(标题:文本(“第二个屏幕”)),主体:中间(子项:文本(“两个”));
}
}
类ScreenOne扩展了无状态小部件{
@凌驾
小部件构建(构建上下文){
返回脚手架(appBar:appBar(标题:文本(“第一屏”)),主体:中心(子:文本(“一”)));
}
}

这样,您的项目中就不会有带有路由名称的字符串,这些字符串在重命名某些内容时可能会被更改、键入错误或忘记。

我想管理我的颤振路由表,如果我使用Switch,会有很多复杂的代码我想管理我的颤振路由表