使用导航栏(NavigationRail)与多个 Futures

huangapple go评论57阅读模式
英文:

Using NavigationRail with multiple Futures

问题

我正在尝试创建一个带有NavigationRail的屏幕,其中每个目标都显示从后端获取的不同数据的表格。

我尝试使用NavigationRail和三个Future来实现它,但每次从一个目标过渡到另一个目标时,我看到第二个目标上出现一个红色屏幕,并且然后过渡完成。我的日志显示以下错误:

构建FutureBuilder<List<dynamic>>时引发了以下TypeErrorImpl
预期值的类型为'D1',但却得到了'D2'之一。

相关错误产生的小部件是FutureBuilder<List<dynamic>>

您能否看一下我是否遗漏了什么?我尝试了相同的方法,使用carousel_slider小部件和三个Future,但没有遇到同样的问题。我猜我在某种程度上误用了NavigationRail。以下是基本代码:

class DataScreen extends StatefulWidget {
  const DataScreen({super.key});

  @override
  State<DataScreen> createState() => _DataScreenState();
}

class _DataScreenState extends State<DataScreen> {
  late Future<List<D1>> data1;
  late Future<List<D2>> data2;
  late Future<List<D3>> data3;

  int _selectedIndex = 0;

  @override
  void initState() {
    super.initState();
    data1 = D1Service().getD1();
    data2 = D2Service().getD2();
    data3 = D3Service().getD3();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Row(
        children: <Widget>[
          NavigationRail(
            selectedIndex: _selectedIndex,
            groupAlignment: 0.0,
            onDestinationSelected: (int index) {
              setState(() {
                _selectedIndex = index;
              });
            },
            labelType: NavigationRailLabelType.all,
            leading: const SizedBox(),
            trailing: const SizedBox(),
            destinations: const <NavigationRailDestination>[
              NavigationRailDestination(
                icon: Icon(Icons.perm_identity),
                selectedIcon: Icon(Icons.person),
                label: Text('D1'),
              ),
              NavigationRailDestination(
                icon: Icon(Icons.groups_outlined),
                selectedIcon: Icon(Icons.groups),
                label: Text('D2'),
              ),
              NavigationRailDestination(
                icon: Icon(Icons.inventory_2_outlined),
                selectedIcon: Icon(Icons.inventory_2),
                label: Text('D3'),
              ),
            ],
          ),
          const VerticalDivider(thickness: 1, width: 1),
          const Spacer(),
          // 这是主要内容。
          Center(
            child: Container(
              child: _toTableAll(),
            ),
          ),
          const Spacer(),
        ],
      ),
    );
  }

  Widget _toTableAll() {
    if (_selectedIndex == 0) {
      return _toTable(data1);
    } else if (_selectedIndex == 1) {
      return _toTable(data2);
    }
    return _toTable(data3);
  }

  Widget _toTable<T>(Future<List<T>> item) {
    return FutureBuilder<List<T>>(
      future: item,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return Container(
            constraints: const BoxConstraints(maxWidth: 800),
            child: MTable(snapshot.data!),
          );
        } else if (snapshot.hasError) {
          return Text('${snapshot.error}');
        } else {
          return const Center(
            child: CircularProgressIndicator(),
          );
        }
      },
    );
  }
}
英文:

I am trying to make a screen with NavigationRail where each destination displays table with different data fetched from backend.

I tried implementing it with NavigationRail and three futures, but each time I transit from one destination to another, I see a red screen with error on a second and then transit completes. My logs show following error:

The following TypeErrorImpl was thrown building FutureBuilder<List<dynamic>>(state: _FutureBuilderState<List<dynamic>>#675cb):
Expected a value of type 'D1', but got one of type 'D2'

The relevant error-causing widget was
FutureBuilder<List<dynamic>>

Could you please see if I am missing something? I tried the same approach with three futures with carousel_slider widget and did not run into a same problem. I guess I am misusing NavigationRail somehow.
Here is base code:

class DataScreen extends StatefulWidget {
const DataScreen({super.key});
@override
State&lt;DataScreen&gt; createState() =&gt; _DataScreenState();
}
class _DataScreenState extends State&lt;DataScreen&gt; {
late Future&lt;List&lt;D1&gt;&gt; data1;
late Future&lt;List&lt;D2&gt;&gt; data2;
late Future&lt;List&lt;D3&gt;&gt; data3;
int _selectedIndex = 0;
@override
void initState() {
super.initState();
data1 = D1Service().getD1();
data2 = D2Service().getD2();
data3 = D3Service().getD3();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Row(
children: &lt;Widget&gt;[
NavigationRail(
selectedIndex: _selectedIndex,
groupAlignment: 0.0,
onDestinationSelected: (int index) {
setState(() {
_selectedIndex = index;
});
},
labelType: NavigationRailLabelType.all,
leading: const SizedBox(),
trailing: const SizedBox(),
destinations: const &lt;NavigationRailDestination&gt;[
NavigationRailDestination(
icon: Icon(Icons.perm_identity),
selectedIcon: Icon(Icons.person),
label: Text(&#39;D1&#39;),
),
NavigationRailDestination(
icon: Icon(Icons.groups_outlined),
selectedIcon: Icon(Icons.groups),
label: Text(&#39;D2&#39;),
),
NavigationRailDestination(
icon: Icon(Icons.inventory_2_outlined),
selectedIcon: Icon(Icons.inventory_2),
label: Text(&#39;D3&#39;),
),
],
),
const VerticalDivider(thickness: 1, width: 1),
const Spacer(),
// This is the main content.
Center(
child: Container(
child: _toTableAll(),
),
),
const Spacer(),
],
),
);
}
Widget _toTableAll() {
if (_selectedIndex == 0) {
return _toTable(data1);
} else if (_selectedIndex == 1) {
return _toTable(data2);
}
return _toTable(data3);
}
Widget _toTable&lt;T&gt;(Future&lt;List&lt;T&gt;&gt; item) {
return FutureBuilder&lt;List&lt;T&gt;&gt;(
future: item,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Container(
constraints: const BoxConstraints(maxWidth: 800),
child: MTable(snapshot.data!),
);
} else if (snapshot.hasError) {
return Text(&#39;${snapshot.error}&#39;);
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
},
);
}
}

答案1

得分: 1

使用snapshot.connectionState == ConnectionState.done替换snapshot.hasData解决了这个问题。

英文:

Changing snapshot.hasData with snapshot.connectionState == ConnectionState.done solved the problem

huangapple
  • 本文由 发表于 2023年2月8日 20:44:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/75385989.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定