#flutter #api #express #stream
#flutter #API #экспресс #поток
Вопрос:
Я пытаюсь получить сообщение от API, который я встроил в express в Flutter.
Дело в том, что для получения моих сообщений мне пришлось создать streambuilder, потому что я хочу, чтобы список сообщений обновлялся при появлении новых сообщений. Для достижения этой цели создайте метод steam, который проверяет API каждые x секунд.
Stream<List<Message>> streamMessage() async* {
final storage = FlutterSecureStorage();
var json = (await storage.read(key: 'user'))!;
User user = User.fromJson(jsonDecode(json));
jwt = user.jwt;
yield* Stream.periodic(const Duration(seconds: 3), (_) async {
http.Response response = await http.get(
Uri.parse("https://myapi.com/messages"),
headers: {
'Authorization': 'Bearer $jwt',
});
List<Message> messages = [];
if (response.statusCode == 200) {
var list = List.from(jsonDecode(response.body)).reversed;
messages = list.map((e) => Message.fromJson(e)).toList();
} else {
log("Error : ${response.statusCode} -- ${response.reasonPhrase}");
}
return messages;
}).asyncMap(
(value) async => await value,
);
}
Это работает, но у него много проблем.
- обновление происходит не так быстро, как я хочу
- это много запросов ни за что
- API может быть легко перегружен
- Этот способ больше похож на обходной путь, чем на реальную функцию
Я хотел бы создать механизм в своем бэкэнде, который больше походил бы на подписку на реальный поток. Как это работает с Firebase. Но я понятия не имею, как это работает или даже что искать.
Если у вас есть какие-либо подсказки, как я могу этого добиться?
Ответ №1:
Вы могли бы достичь этого с помощью websockets, для чего потребуется некоторая настройка вашего приложения node и вашего приложения Flutter.
Я бы предложил использовать сокет Flutter.клиент ввода-вывода и сокет узла.сервер ввода-вывода.
Обратите внимание, что стабильная версия клиента flutter не соответствует текущей версии сервера узла. Вы можете использовать бета-версию 2 клиента flutter или более старую версию сервера.
В прошлый раз, когда я это настраивал, я выбрал последнее. Version 1.01
клиент определенно работает с узловым сервером version 2.4.1
.
Вот простой пример с виджетом с отслеживанием состояния, но если вы хотите использовать StreamBuilder
, на странице client pub.dev есть пример. Его можно привязать к любому решению для управления состоянием.
class SocketExample extends StatefulWidget {
const SocketExample({Key? key}) : super(key: key);
@override
_SocketExampleState createState() => _SocketExampleState();
}
class _SocketExampleState extends State<SocketExample> {
static const _sockerURL = 'your node app url';
static const _socketEvent = 'event_1';
final _socket = IO.io(sockerURL, <String, dynamic>{
"transports": ["websocket"],
"autoConnect": false,
});
@override
void initState() {
super.initState();
_socket.connect();
_socket.onConnect((data) {
log('Connected ${_socket.connected}');
});
_socket.on(socketEvent, (message) {
// whatever needs to happen when you get an event from the server
// put it here
});
}
@override
void dispose() {
_socket.disconnect();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ...
}
}
И базовая настройка на стороне узла будет выглядеть примерно так
const server = http.createServer(app);
const io = require("socket.io")(server);
const socketEvent = "event_1"; // this string needs to correspond to the event in your flutter app
io.on("connection", (socket) => {
socket.on(socketEvent, (msg) => {
io.emit(socketEvent, msg);
console.log("message: " msg);
});
});
Затем в зависимости от GET / POST и т. Д… вам нужно в узле, с которым вы отправляете сообщение для Flutter
io.emit(socketEvent, whatever the payload to your Flutter app is goes here);
Это практически все, что вам нужно сделать, чтобы получать обновления во Flutter в режиме реального времени из приложения узла без ручного обновления или проверки API с любым интервалом.