一個網(wǎng)絡(luò)請求方法不斷的接收stream圖片流事件断医,需要將這些圖片流展示在Image控件上敷扫,這樣就能夠?qū)崿F(xiàn)讓圖片變成視頻的效果:
直接上代碼
import 'dart:async';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class TestApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'IPCamera'),
);
}
}
List<int> _bytes = [];
Uint8List lastImageData = Uint8List(0);
class MyHomePage extends StatefulWidget {
final String title;
MyHomePage({this.title});
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final StreamController _streamController = StreamController();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
children: [
Container(
height: 60,
child: _topButton(),
),
StreamBuilder(
builder: (BuildContext context, AsyncSnapshot snapshot) {
return Image.memory(
consolidateHttpClientResponseBytes(snapshot.data));
},
stream: _streamController.stream,
initialData: Uint8List(0),
),
],
));
}
Future _loadImagesData() async {
var uri = Uri.parse("http://192.168.4.1:81/stream");
var response = await http.Client().send(http.Request('GET',uri));
response.stream.listen((value) {
print(response.request.toString());
_bytes.addAll(value);
if (lastImageData.length == 36) {
_streamController.sink.add(_bytes);
_bytes = [];
}
lastImageData = Uint8List.fromList(value);
print('當(dāng)前數(shù)據(jù)字節(jié)長度${(lastImageData.length)}');
});
}
Widget _topButton() {
return Center(
child: TextButton(
style: ButtonStyle(
foregroundColor: MaterialStateProperty.resolveWith(
(states) {
if (states.contains(MaterialState.focused) &&
!states.contains(MaterialState.pressed)) {
//獲取焦點時的顏色
return Colors.green;
} else if (states.contains(MaterialState.pressed)) {
//按下時的顏色
return Colors.red;
}
//默認狀態(tài)使用灰色
return Colors.white;
},
),
padding: MaterialStateProperty.all(EdgeInsets.all(10)),
minimumSize: MaterialStateProperty.all(Size(100, 50)),
backgroundColor: MaterialStateProperty.resolveWith((states) {
//設(shè)置按下時的背景顏色
if (states.contains(MaterialState.pressed)) {
return Colors.yellowAccent[200];
}
//默認不使用背景顏色
return Colors.blue;
}),
),
onPressed: () {
_loadImagesData();
},
child: Text('請求')),
);
}
static consolidateHttpClientResponseBytes(data) {
// response.contentLength is not trustworthy when GZIP is involved
// or other cases where an intermediate transformer has been applied
// to the stream.
final List<List<int>> chunks = <List<int>>[];
int contentLength = 0;
chunks.add(data);
contentLength += data.length;
final Uint8List bytes = Uint8List(contentLength);
int offset = 0;
for (List<int> chunk in chunks) {
bytes.setRange(offset, offset + chunk.length, chunk);
offset += chunk.length;
}
return bytes;
}
}
這里的網(wǎng)絡(luò)請求用的是http框架,沒使用dio框架,不知道是我不會用還是本身就沒有這種對流請求的方法菱涤。
導(dǎo)入的是http庫:
http: ^0.13.1
其實這里有個問題,我不知道每次傳回來的流啥時候是一張完整的圖片流慕购,通過觀察數(shù)據(jù)震桶,發(fā)現(xiàn)每次剛接收的時候長度是36,于是做了下處理毫蚓。但實際上這樣是不對的占键,暫時沒有找到解決方案,如果有人知道的話元潘,請不吝賜教畔乙。