- 總結問題:
我的應用程式向服務器發送資訊,服務器回應成功或失敗。我在更新AlertDialog網路通信的結果時遇到問題。當用戶保存他們的設定時,我將多個專案發送到服務器,我需要跟蹤所有設定是否已成功發送。因此,當所有設定成功發送后,我可以AlertDialog成功更新。我在當前實作中看到的問題是,TextButton在我看到正確的訊息之前,我需要兩次激活。AlertDialog在第一次TextButton按下標記為 "save"后應該顯示正確的訊息。我需要解決的一種情況是服務器關閉并且應用程式的連接請求超時。然后我需要使用類似的東西CircularProgressIndicator 因此用戶可以在網路通信完成時等待。
變數successPrompt是包含帶有網路事務結果的訊息的內容。這需要在AlertDialog彈出時更新為正確的訊息。
2:我試過的:
我試過使用FutureBuilder來創建,AlertDialog但我得到了相同的結果。AlertDialog當我知道網路事務的結果時,我需要一種方法來調出。發生的情況是AlertDialog將被啟動,但應用程式仍在后臺嘗試連接到服務器。完成此步驟并關閉套接字后,我想調出小部件。
3:這是相關的代碼。請不要介意除錯列印和注釋掉的代碼。
import 'package:flutter/material.dart';
import 'dart:io';
import 'globals.dart';
import 'dart:convert' show utf8;
import 'package:local_auth/local_auth.dart';
class SystemsSettingsPage extends StatefulWidget {
final int index;
SystemsSettingsPage({ required this.index});
@override
_SystemsSettingsPage createState() => _SystemsSettingsPage();
}
class _SystemsSettingsPage extends State<SystemsSettingsPage> {
bool tileValTemp = false;
bool tileValDetect = false;
bool tileValCamOff = false;
bool tileValSystem = false;
bool connected = false;
int successCount = 0;
String successPrompt = "";
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
backgroundColor: Colors.blueAccent,
title: Text("Base Station Settings"),
),
body: Column(
children: <Widget> [
SwitchListTile(value: tileValDetect,
onChanged: (bool val){ setState(() {
tileValDetect = val;
});},
title: Text('Detection notifications', style: TextStyle(color: Colors.white))
),
SwitchListTile(value: tileValTemp,
onChanged: (bool val){ setState(() {
tileValTemp = val;
});},
title: Text('Temperature threshold out of range', style: TextStyle(color: Colors.white))
),
TextButton(
child: const Text("save", style: TextStyle(fontSize: 20.0)),
style: ButtonStyle(foregroundColor: MaterialStateProperty.all<Color>(Colors.white),
padding: MaterialStateProperty.all<EdgeInsets>(EdgeInsets.all(10.0)),
backgroundColor: MaterialStateProperty.all<Color>(Colors.blueAccent)),
onPressed: () {
//successPrompt = "Loading.. Wait 5 seconds to update.";
successCount = 0;
Socket.connect(baseStationAddresses[0], baseStationPort,timeout: Duration(seconds: 5)).then(
(socket) {
print('Connected to: '
'${socket.remoteAddress.address}:${socket
.remotePort}');
String command = "SETSYSTEM," baseStationNames[0] ",detectMotion," "$tileValDetect";
socket.write(command);
socket.listen((data) {
String socketData = utf8.decode(data);
if(socketData == "REQUEST_CONFIRMED") {
successCount = 1;
}
},
onDone: () {
socket.destroy();
},
);
},
).catchError((onError) {
print("here 1");
successPrompt = "There was a problem. Please retry.";
});
Socket.connect(baseStationAddresses[0], baseStationPort,timeout: Duration(seconds: 5)).then(
(socket) {
print('Connected to: '
'${socket.remoteAddress.address}:${socket
.remotePort}');
String command = "SETSYSTEM," baseStationNames[0] ",tempThreshold," "$tileValTemp";
socket.write(command);
socket.listen((data) {
String socketData = utf8.decode(data);
if(socketData == "REQUEST_CONFIRMED") {
successCount = 1;
}
},
onDone: () {
print("SuccessCount $successCount");
if(successCount == 2)
{
print("here 2");
successPrompt = "Setting successfully saved.";
}
else
{
print("here 3");
successPrompt = "Couldn't save, please retry.";
}
socket.destroy();
},
);
}
).catchError((onError) {
print("here 4");
successPrompt = "There was a problem. Please retry.";
});
showDialog(context: context, builder: (context) =>
AlertDialog(
title: Text("Save results"),
content: Text(successPrompt),
actions: <Widget>[
TextButton(onPressed: () => Navigator.pop(context),
child: const Text("OK"),
)
]
)
);
/*
FutureBuilder<String>(
future: getSaveStatus(),
builder: (context, snapshot) {
String nonNullableString = snapshot.data ?? 'Error';
if(snapshot.hasData) {
return AlertDialog(
title: Text("Save results"),
content: Text(nonNullableString),
actions: <Widget>[
TextButton(onPressed: () => Navigator.pop(context),
child: const Text("OK"),
)
]
);
}
return Center(child: CircularProgressIndicator());
},
);*/
}
),
Center(
child:ClipRRect(
borderRadius: BorderRadius.circular(4),
child: Stack(
children: <Widget>[
Positioned.fill(
child: Container(
decoration: const BoxDecoration(
color: Colors.red,
),
),
),
TextButton(
style: TextButton.styleFrom(
padding: const EdgeInsets.all(16.0),
primary: Colors.white,
textStyle: const TextStyle(fontSize: 20),
),
onPressed: () {},
child: const Text('Remove System'),
),
],
),
),
)
],
)
);
}
Future<String> getSaveStatus() async {
return await new Future(() => successPrompt);
}
}
任何建議都會有所幫助。
uj5u.com熱心網友回復:
將對話框的內容包裝在 StatefulBuilder 中,直到您的 AlertDialog 表現為無狀態小部件,請參閱:
await showDialog<void>(
context: context,
builder: (BuildContext context) {
int selectedRadio = 0;
return AlertDialog(
content: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Text(successPrompt);
},
),
);
},
);
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/388064.html
