firebase - 如何协调 StreamBuilder 的授权和 FutureBuilder 的数据来自 api 和 listview 过滤
问题描述
首先,我是新手,我可以犯一些基本的错误。
初步假设:
- 使用带有 firebase 身份验证的颤振
- 使用自己的 api 获取更多数据
- 当应用程序在标头中从 firebase 身份验证发送用户令牌时,api 端点返回更多数据
我的主要课程:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => GoogleSignInProvider(),
child: MaterialApp(
home: child: MyList()
);
}
还有 MyList 类(我在这个例子中简化了这个类):
class MyList extends StatefulWidget {
MyList();
@override
_MyListState createState() => _MyListState();
}
class _MyListState extends State<MyList> {
TextEditingController controller = new TextEditingController();
late Future<List<Details>> _detailsList;
Future<List<Details>> getDetailsList() async {
Map<String, String> headers = {};
if (FirebaseAuth.instance.currentUser != null){
headers["tokenID"] = FirebaseAuth.instance.currentUser?.uid;
}
final response = await http
.get(Uri.parse('http://hostname/api/v1/details/list'), headers: headers);
final responseJson = json.decode(response.body);
List<Details> details = [];
for (Map details in responseJson["details"]) {
details.add(Details.fromJson(details));
}
return details;
}
@override
void initState() {
super.initState();
_details = getDetailsList();
}
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, snapshot) {
return FutureBuilder(
future: _details,
builder: (context, AsyncSnapshot<List<Details>> snapshot) {
return new Scaffold(
body: new Column(
children: <Widget>[
new TextField(
controller: controller,
decoration: new InputDecoration(
hintText: 'Search', border: InputBorder.none),
onChanged: onSearchTextChanged,
),
new Expanded(
child: _searchResult.length != 0 ||
controller.text.isNotEmpty
? new ListView.builder(
padding: const EdgeInsets.only(top: 10, bottom: 50),
itemCount: _searchResult.length,
itemBuilder: (context, i) {
return new ListItem(_searchResult[i]);
},
)
: new ListView.builder(
padding: const EdgeInsets.only(bottom: 40),
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
return new ListItem(snapshot.data![index]);
},
),
),
],
),
);
}
);
}
);
}
List<Details> _searchResult = [];
onSearchTextChanged(String text) async {
_searchResult.clear();
if (text.isEmpty) {
setState(() {});
return;
}
_details.forEach((userDetail) {
if (userDetail.name.toLowerCase().contains(text.toLowerCase()))
_searchResult.add(userDetail);
});
setState(() {});
}
在这种情况下,过滤/搜索工作正常。但是每个键入的字符都会执行 setState 和重新启动小部件,这会导致为每种类型发送 API 请求 - 我不希望这种行为。
另一方面,我想在用户登录或注销时获得一个新的 API 请求。
我怎样才能做到这一点?
解决方案
回答问题的第一部分:为了防止每个键入字符的 setState,您需要为您的 TextField 实现去抖动和节流。肯定有很多教程。
对第二部分的回答:获取firebase auth流,在每次需要时根据auth对象在请求的流上执行asyncMap。asyncMap 之后的流将返回 List,并且会在每次 auth 流更新时更新。
推荐阅读
- javascript - 是否可以在 React 中使用嵌套在 BrowserRouter 中的 MemoryRouter?
- reactjs - 多个输入值反应
- git - 将旧分支合并为新分支或将新分支合并为旧分支
- javascript - 单击后重复 div 元素
- visual-studio-code - Pylance 不允许我导航到源代码,而是将我带到 .pyi 存根
- flutter - 颤动如何从数据库中获取谷歌地图标记
- android-studio - 如何在课堂上截取我的 android studio 代码
- python - 从 DataFrame Pandas 中删除索引列
- python - 使用 Zip 函数的错误是返回缺失的结果
- javascript - 如何设置a的默认值