flutter通过GlobalKey在自定义Widget外部获取其state刷新页面
Posted 一叶飘舟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了flutter通过GlobalKey在自定义Widget外部获取其state刷新页面相关的知识,希望对你有一定的参考价值。
PageA的定义如下
class PageA extends StatefulWidget
PageA(Key key) : super(key: key);
@override
PageAState createState()
return PageAState();
class PageAState extends State<PageA>
static GlobalKey homeKey = GlobalKey();
//关键代码
static currentInstance()
var state = PageAState.homeKey.currentContext.findAncestorStateOfType();
return state;
@override
Widget build(BuildContext context)
// TODO: implement build
return return Scaffold(
key: homeKey,
body: Container();
);
reloadData()
setState(() );
在 PageB 里调用 PageAState 的 reloadData() 方法
class PageB
buttonClick()
PageAState.currentInstance().reloadData();
注意:
如果PageA没有被打开过,调用 PageAState.currentInstance().reloadData()是会出现空指针的。
需要加空判断。
var state = PageAState.homeKey.currentContext?.findAncestorStateOfType< PageAState >();
调用的时候:
PageAState.currentInstance()?.reloadData();
Flutter中父widget调用子widget的第二种方法
大致步骤:
一、
定义globalKey,注意<>中是子widget的State类。
final _childWidgetKey = GlobalKey();
二、在父页面初始化子widget
ChildPage(key:_receiveKey),
三、
class ChildPage extends StatefulWidget
ChildPage(Key key) : super(key: key);
@override
ChildPageState createState() => ChildPageState();
四、
在父界面调用子widget中的方法
_childWidgetKey.currentState.onRefresh();
使用GlobalKey实现父布局调用子布局方法完成视频url切换播放 & 视频url中文件名中文导致无法播放的问题
video_player: ^2.1.10
chewie: ^1.2.2
当把chewie封装到一个Widget - VideoPlayer,在父布局调用初始化第一个视频url后,发现不知如何切换视频url。
自己封装的VideoPlayer中封装了切换视频的方法
//切换视频url
switchVideo(String url,bool isAuto)
_videoPlayerController.pause();
setState(()
_prepareVideo(url,isAuto);
);
void _prepareVideo(String url, bool isAuto)
_url = url;
//解决视频url中文件名中文导致无法播放的问题
if (!url.contains('%'))
int index = url.lastIndexOf('/');
String prefix = url.substring(0, index + 1);
String subfix = url.substring(index + 1);
var encodeSubfix = Uri.encodeComponent(subfix).toString();
_url = prefix + encodeSubfix;
print('编码后:' + _url);
_videoPlayerController = VideoPlayerController.network(_url);
_chewieController = ChewieController(
videoPlayerController: _videoPlayerController,
autoPlay: isAuto,
aspectRatio: widget.aspectRatio,
//customControls: CustomControls(),
);
父布局调用子布局方法
关键方法:
final GlobalKey<子布局State> _globalKey = GlobalKey(); //一般子布局state时设置成私有的,此时需要去掉_
取得子组件的state对象: _globalKey.currentState.子布局方法()
父布局使用的是Stateful,在父布局State类中定义GlobalKey变量
final GlobalKey<VideoPlayerState> _globalKey = GlobalKey();
使用子组件VideoPlayer时,通过key传给子组件
VideoPlayer(
key: _globalKey,
playUrl: _courseDatas[_currentVideoIndex].videoUrl,
autoPlay: true,
)
切换视频:
void _play(CourseData course)
_currentVieo = course;
_currentVideoIndex = _courseDatas.indexOf(course);
print('current index = $_currentVideoIndex');
setState(() );
//when is first play,when is switch?
_globalKey.currentState!.switchVideo(course.videoUrl, true);
url中带有中文导致视频播放器无法播放的问题分析
原因:
在ios中,访问HTTP/HTTPS时,url中存在中文或者特殊字符时,会导致无法正常的访问到资源或服务,想要解决这个问题,需要对url进行编码。
网络标准RFC 1738规定url中只能包含英文字母和阿拉伯数字,以及一些特殊字符。“只有字母和数字[0-9a-zA-Z]、和特殊符号”$-_.+!*’(),”[不包括双引号]、及某些保留字,才可以不经过编码直接用于URL。”
dart中对url进行编码:
Uri.encodeComponent(url);
Uri.decodeComponent(encodedUrl);
_url = url;
//解决视频url中文件名中文导致无法播放的问题
if (!url.contains('%'))
int index = url.lastIndexOf('/');
String prefix = url.substring(0, index + 1);
String subfix = url.substring(index + 1);
var encodeSubfix = Uri.encodeComponent(subfix).toString();
_url = prefix + encodeSubfix;
print('编码后:' + _url);
注意:
- 上文中的url编码方式,仅适用于只有最后的文件名中含有中文的情况,且未测试更多复杂的文件名情况
- 上文中的方式,因为服务器返回的url,部分是已经对中文编码的,部分没有,所以粗暴地根据url文件名部分是否含有%来判定是否已经编码
- 更好的方式应当检查判定url中是否含有中文以及非RFC 1738规定字符以外的字符,并对这部分字符进行编码
- 若我直接对全url进行编码,就会对其他字符也编码了, 导致新的url即使在Chrome中也无法访问
Flutter:获取状态state的几种方式
1,通过GlobalKey获取到state
在Scaffold中设置key为GlobalKey,然后在使用的地方通过GlobalKey获取
class StatefullDemo extends StatelessWidget
static GlobalKey<ScaffoldState> _globalKey = GlobalKey();
@override
Widget build(BuildContext context)
return Scaffold(
key: _globalKey,
......
......
ScaffoldState _state = _globalKey.currentState;
2,通过查找父级最近的Scaffold对应的ScaffoldState对象
如果使用是在StatelessWidget中,则可以直接获取到widget上下文的content,直接使用context.findAncestorStateOfType获取到state
ScaffoldState _state =
context.findAncestorStateOfType<ScaffoldState>();
如果需要在StatefulWidget 的 State中使用呢?如何获取到widget中的state?
此时可以通过Builder来构建widget,Builder会将widget节点的context作为回调参数
Builder(builder: (context)
return RaisedButton(
onPressed: ()
ScaffoldState _state = context.findAncestorStateOfType();
SnackBar snackBar = SnackBar(content: Text('RaisedButton'));
_state.showSnackBar(snackBar);
ScaffoldState _state1 = this as ScaffoldState;
,
child: Text('RaisedButton'),
);
),
以上是关于flutter通过GlobalKey在自定义Widget外部获取其state刷新页面的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Flutter 中的 Form 需要 GlobalKey?
Flutter 使用 GlobalKey 从另一个类更改状态