gpt4 book ai didi

flutter - 如何在Flutter中重新访问时保存页面状态

转载 作者:行者123 更新时间:2023-12-03 04:46:59 24 4
gpt4 key购买 nike

我有2个屏幕,正在尝试了解如何实现页面状态。例如,在下面的屏幕中,我有4个选项,所有这些选项都将用户带到同一屏幕,唯一的区别是调用API的方法不同,因为每个API生成一个列表都是不同的。我正在尝试处理后退箭头 Action ,这就是我遇到的问题。

用例-
当用户在屏幕2上时,他正在播放歌曲,现在回到背面,继续播放歌曲。现在,当用户再次从屏幕1中选择相同的选项时,我想显示相同的列表,而无需重新加载和选择。如果用户选择任何其他选项,它应该表现正常,这是可行的。

解决方案-

  • 我可以对加载的歌曲列表进行硬编码,然后发送回屏幕1,然后通过选择再次将其取回,但这将占用大量资源。
  • AutomaticKeepAliveClientMixin我尝试了本教程,但没有帮助或保持状态为 Activity 。
  • PageStorage是我看到的第三个选项,但是我发现大部分时间都在有标签的应用程序上使用。

  • enter image description here enter image description here

    屏幕1-
    class Dashboard  extends StatefulWidget {
    int playingId;
    Dashboard({this.playingId});
    @override
    _DashboardState createState() => _DashboardState(playingId);


    }

    class _DashboardState extends State<Dashboard> {
    String appname;
    int playingId = 0;
    _DashboardState(this.playingId);
    // print('${playingId}');

    @override
    void initState() {
    appname="";
    // playingId=0;
    }

    @override
    Widget build(BuildContext context) {
    return Scaffold(
    appBar: AppBar(
    elevation: 0,
    backgroundColor: AppColors.darkBlue,
    centerTitle: true,
    title: Text("Tirthankar",
    style: TextStyle(color: Colors.white),),
    ),

    backgroundColor: AppColors.styleColor,
    body: Column(
    children: <Widget>[
    // SizedBox(height: 5),
    Padding(
    padding: const EdgeInsets.all(20),
    child: Row(
    mainAxisAlignment: MainAxisAlignment.spaceBetween,
    children: <Widget>[
    CustomGridWidget(
    child: Icon(
    Icons.file_download,
    size: 100,
    color: AppColors.styleColor,
    ),

    // image: 'assets/bhaktambar.png',
    sizew: MediaQuery.of(context).size.width * .4,
    sizeh: MediaQuery.of(context).size.width * .5,
    borderWidth: 2,
    label: "Bhakti",
    onTap: () {
    Navigator.of(context).push(
    MaterialPageRoute(
    builder: (_) => ListPage(appname: "Kids",playingId: playingId,),

    ),
    );
    },
    ),
    CustomGridWidget(
    child: Icon(
    Icons.file_download,
    size: 100,
    color: AppColors.styleColor,
    ),

    // image: 'assets/bhaktambar.png',
    sizew: MediaQuery.of(context).size.width * .4,
    sizeh: MediaQuery.of(context).size.width * .5,
    borderWidth: 2,
    label: "Kids",
    onTap: () {
    Navigator.of(context).push(
    MaterialPageRoute(
    builder: (_) => ListPage(appname: "Kids",playingId: playingId,),

    ),
    );
    },
    ),
    ],
    ),
    ),
    Padding(
    padding: const EdgeInsets.only(
    left: 20,
    right: 20,
    bottom: 20),
    child: Row(

    mainAxisAlignment: MainAxisAlignment.spaceBetween,
    children: <Widget>[
    CustomGridWidget(
    child: Icon(
    Icons.favorite,
    size: 100,
    color: AppColors.styleColor,
    ),
    // image: 'assets/kids.jpg',
    sizew: MediaQuery.of(context).size.width * .4,
    sizeh: MediaQuery.of(context).size.width * .5,
    borderWidth: 2,
    label: "Favorite",
    onTap: () {
    Navigator.of(context).push(
    MaterialPageRoute(
    builder: (_) => ListPage(appname: "Songs"),
    ),
    );
    },
    ),
    Align(
    alignment: Alignment.center,
    child: CustomGridWidget(
    child: Icon(
    Icons.book,
    size: 100,
    color: AppColors.styleColor,
    ),
    // image: 'assets/vidyasagar.jpg',
    sizew: MediaQuery.of(context).size.width * .4,
    sizeh: MediaQuery.of(context).size.width * .5,
    borderWidth: 2,
    onTap: () {
    Navigator.of(context).push(
    MaterialPageRoute(
    builder: (_) => ListPage(appname: "Bhajan"),
    ),
    );
    },
    ),
    ),
    ],
    ),
    ),
    ]
    ),





    );
    }
    Material boxTiles(IconData icon, String name){
    return Material(

    color: AppColors.mainColor,
    elevation: 14.0,
    shadowColor: AppColors.styleColor,
    borderRadius: BorderRadius.circular(24.0),
    child: Center(
    child: Padding(
    padding: const EdgeInsets.all(8.0),
    child:Row(
    mainAxisAlignment: MainAxisAlignment.center,

    children: <Widget>[
    Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: <Widget>[
    InkWell(
    onTap: (){print("tapped"); /* or any action you want */ },
    child: Container(
    width: 130.0,
    height: 10.0,
    color : Colors.transparent,
    ), // container
    ), //
    //Text
    Padding(
    padding: const EdgeInsets.all(8.0),
    child: Text(name,
    style:TextStyle(
    color: AppColors.styleColor,
    fontSize: 20.0,
    )
    ),
    ),
    //Icon
    Material(
    color: AppColors.styleColor,
    borderRadius: BorderRadius.circular(50.0),
    child: Padding(padding: const EdgeInsets.all(10.0),
    child: Icon(icon, color: AppColors.lightBlue,size: 30,),
    ),
    ),
    ],
    )
    ],
    )
    ),
    )
    );
    }

    }

    屏幕2-
    // import 'dart:js';


    class ListPage extends StatefulWidget {
    String appname;
    int playingId;
    ListPage({this.appname,this.playingId});
    @override
    _ListPageState createState() => _ListPageState(appname,playingId);
    }

    class _ListPageState extends State<ListPage>
    with SingleTickerProviderStateMixin,AutomaticKeepAliveClientMixin<ListPage> {
    String appname;
    int playingId;
    bool isPlaying = false;
    _ListPageState(this.appname,playingId);
    // List<MusicModel> _list1;
    List<MusicData> _list;

    var _value;
    int _playId;
    int _songId;
    String _playURL;

    bool _isRepeat;
    bool _isShuffle;
    bool _isFavorite;
    String _startTime;
    String _endTime;
    AnimationController _controller;
    Duration _duration = new Duration();
    Duration _position = new Duration();
    final _random = new Random();
    AudioPlayer _audioPlayer = AudioPlayer();
    @override
    void initState() {
    _playId = 0;
    // _list1 = MusicModel.list;
    this._fileUpdate();
    // _list = _list1;
    _controller =
    AnimationController(vsync: this, duration: Duration(microseconds: 250));
    _value = 0.0;
    _startTime = "0.0";
    _endTime = "0.0";
    _isRepeat = false;
    _isShuffle = false;
    _isFavorite = false;



    _audioPlayer.onAudioPositionChanged.listen((Duration duration) {
    setState(() {
    // _startTime = duration.toString().split(".")[0];
    _startTime = duration.toString().split(".")[0];
    _duration = duration;

    // _position = duration.toString().split(".")[0];
    });
    });
    _audioPlayer.onDurationChanged.listen((Duration duration) {
    setState(() {
    _endTime = duration.toString().split(".")[0];
    _position = duration;
    });
    });
    _audioPlayer.onPlayerCompletion.listen((event) {
    setState(() {
    isPlaying = false;
    _position = _duration;
    if (_isRepeat) {
    _songId = _songId;
    } else {
    if (_isShuffle) {
    var element = _list[_random.nextInt(_list.length)];
    _songId = element.id;
    } else {
    _songId = _songId + 1;
    }
    }
    _player(_songId);
    });
    });

    super.initState();
    }

    bool get wantKeepAlive => true;

    @override
    Widget build(BuildContext context) {
    super.build(context);
    return Scaffold(
    appBar: AppBar(
    elevation: 0,
    backgroundColor: AppColors.mainColor,
    centerTitle: true,
    leading: IconButton(
    icon: Icon(Icons.arrow_back),
    onPressed: (){
    Navigator.of(context).push(
    MaterialPageRoute(
    builder: (_) => Dashboard(playingId: _songId),
    ),
    );
    },
    ),
    title: Text(
    appname,
    style: TextStyle(color: AppColors.styleColor),
    ),
    ),



    backgroundColor: AppColors.mainColor,
    body: Stack(
    children: <Widget>[
    Column(
    children: <Widget>[
    Padding(
    padding: const EdgeInsets.all(24.0),
    child: Row(
    mainAxisAlignment: MainAxisAlignment.spaceBetween,
    children: <Widget>[
    CustomButtonWidget(
    child: Icon(
    Icons.favorite,
    color: AppColors.styleColor,
    ),
    size: 50,
    onTap: () {},
    ),
    CustomButtonWidget(
    image: 'assets/logo.jpg',
    size: 100,
    borderWidth: 5,
    onTap: () {
    Navigator.of(context).push(
    MaterialPageRoute(
    builder: (_) => DetailPage(),
    ),
    );
    },
    ),
    CustomButtonWidget(
    child: Icon(
    Icons.menu,
    color: AppColors.styleColor,
    ),
    size: 50,
    onTap: () {
    Navigator.of(context).push(
    MaterialPageRoute(
    builder: (_) => HomePage(),
    ),
    );
    },
    )
    ],
    ),
    ),
    slider(),
    Padding(
    padding: const EdgeInsets.symmetric(horizontal: 15),
    child: Row(
    mainAxisAlignment: MainAxisAlignment.spaceBetween,
    children: <Widget>[
    IconButton(
    icon: Icon(
    _isRepeat ? Icons.repeat_one : Icons.repeat,
    color: _isRepeat ? Colors.brown : AppColors.styleColor,
    ),
    onPressed: () {
    if (_isRepeat) {
    _isRepeat = false;
    } else {
    _isRepeat = true;
    }
    },
    ),
    IconButton(
    icon: Icon(
    isPlaying ? Icons.pause : Icons.play_arrow,
    color: AppColors.styleColor,
    ),
    onPressed: () {
    if (isPlaying) {
    _audioPlayer.pause();
    setState(() {
    isPlaying = false;
    });
    } else {
    if (!isPlaying){
    _audioPlayer.resume();
    setState(() {
    isPlaying = true;
    });
    }

    }
    }),
    IconButton(
    icon: Icon(
    Icons.stop,
    color: AppColors.styleColor,
    ),
    onPressed: () {
    if (isPlaying){
    _audioPlayer.stop();
    setState(() {
    isPlaying = false;
    _duration = new Duration();
    });
    }

    // isPlaying = false;
    }),
    IconButton(
    icon: Icon(
    Icons.shuffle,
    color:
    _isShuffle ? Colors.brown : AppColors.styleColor,
    ),
    onPressed: () {
    if (_isShuffle) {
    _isShuffle = false;
    } else {
    _isShuffle = true;
    }
    }),
    ],
    ),
    ),

    Expanded(
    //This is added so we can see overlay else this will be over button
    child: ListView.builder(
    physics:
    BouncingScrollPhysics(), //This line removes the dark flash when you are at the begining or end of list menu. Just uncomment for
    // itemCount: _list.length,
    itemCount: _list == null ? 0 : _list.length,
    padding: EdgeInsets.all(12),
    itemBuilder: (context, index) {
    return GestureDetector(
    onTap: () {
    _songId = index;
    _player(index);
    },
    child: AnimatedContainer(
    duration: Duration(milliseconds: 500),
    //This below code will change the color of sected area or song being played.
    decoration: BoxDecoration(
    color: _list[index].id == _playId
    ? AppColors.activeColor
    : AppColors.mainColor,
    borderRadius: BorderRadius.all(
    Radius.circular(20),
    ),
    ),
    //End of row color change
    child: Padding(
    padding: const EdgeInsets.all(
    16), //This will all padding around all size
    child: Row(
    mainAxisAlignment: MainAxisAlignment
    .spaceBetween, //This will allign button to left, else button will be infront of name
    children: <Widget>[
    Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: <Widget>[
    Text(
    _list[index].title,
    style: TextStyle(
    color: AppColors.styleColor,
    fontSize: 16,
    ),
    ),
    Text(
    _list[index].album,
    style: TextStyle(
    color: AppColors.styleColor.withAlpha(90),
    fontSize: 16,
    ),
    ),
    ],
    ),
    IconButton(
    icon: Icon(_isFavorite
    ? Icons.favorite
    : Icons.favorite_border),
    onPressed: () {
    if (_isFavorite) {
    _isFavorite = false;
    } else {
    _isFavorite = true;
    }
    })
    //Diabled Play button and added fav button.
    // CustomButtonWidget(
    // //This is Play button functionality on list page.
    // child: Icon(
    // _list[index].id == _playId
    // ? Icons.pause
    // : Icons.play_arrow,
    // color: _list[index].id == _playId
    // ? Colors.white
    // : AppColors.styleColor,
    // ),
    // size: 50,

    // isActive: _list[index].id == _playId,
    // onTap: () async {
    // _songId = index;
    // _player(index);
    // },
    // )
    ],
    ),
    ),
    ),
    );
    },
    ),
    )
    ],
    ),
    Align(
    alignment: Alignment.bottomCenter,
    child: Container(
    height: 50,
    decoration: BoxDecoration(
    gradient: LinearGradient(
    colors: [
    AppColors.mainColor.withAlpha(0),
    AppColors.mainColor,
    ],
    begin: Alignment.topCenter,
    end: Alignment.bottomCenter,
    )),
    ),
    )
    ],
    ),
    // floatingActionButton: FloatingActionButton(
    // child: Icon(Icons.music_note),
    // onPressed: () async { // String filePath = await FilePicker.getFilePath();

    // int status = await _audioPlayer.play("https://traffic.libsyn.com/voicebot/Jan_Konig_on_the_Jovo_Open_Source_Framework_for_Voice_App_Development_-_Voicebot_Podcast_Ep_56.mp3");
    // if (status == 1){
    // setState(() {
    // isPlaying = true;
    // });
    // }
    // },
    // )
    );
    }

    Widget slider() {
    return Slider(
    activeColor: AppColors.styleColor,
    inactiveColor: Colors.lightBlue,
    value: _duration.inSeconds.toDouble(),
    min: 0.0,
    max: _position.inSeconds.toDouble(),
    divisions: 10,
    onChangeStart: (double value) {
    print('Start value is ' + value.toString());
    },
    onChangeEnd: (double value) {
    print('Finish value is ' + value.toString());
    },
    onChanged: (double value) {
    setState(() {
    seekToSecond(value.toInt());
    value = value;
    });
    });
    }

    Future<Void> _fileUpdate() async {
    String url =
    "azonaws.com/input.json";
    String arrayObjsText = "";
    try {
    eos.Response response;
    Dio dio = new Dio();
    response = await dio.get(url,options: Options(
    responseType: ResponseType.plain,
    ),);
    arrayObjsText = response.data;
    print(response.data.toString());
    } catch (e) {
    print(e);
    }
    var tagObjsJson = jsonDecode(arrayObjsText)['tags'] as List;
    this.setState(() {
    _list = tagObjsJson.map((tagJson) => MusicData.fromJson(tagJson)).toList();
    });

    // return _list;
    // print(_list);
    }

    Future<void> _player(int index) async {
    if (isPlaying) {
    if (_playId == _list[index].id) {
    int status = await _audioPlayer.pause();
    if (status == 1) {
    setState(() {
    isPlaying = false;
    });
    }
    } else {
    _playId = _list[index].id;
    _playURL = _list[index].songURL;
    _audioPlayer.stop();
    int status = await _audioPlayer.play(_playURL);
    if (status == 1) {
    setState(() {
    isPlaying = true;
    });
    }
    }

    } else {
    _playId = _list[index].id;
    _playURL = _list[index].songURL;
    int status = await _audioPlayer.play(_playURL);
    if (status == 1) {
    setState(() {
    isPlaying = true;
    });
    }
    }
    }




    String _printDuration(Duration duration) {
    String twoDigits(int n) {
    if (n >= 10) return "$n";
    return "0$n";
    }

    String twoDigitMinutes = twoDigits(duration.inMinutes.remainder(60));
    String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60));
    return "${twoDigits(duration.inHours)}:$twoDigitMinutes:$twoDigitSeconds";
    }

    void seekToSecond(int second) {
    Duration newDuration = Duration(seconds: second);
    _audioPlayer.seek(newDuration);
    }


    }

    最佳答案

    PageStorage is 3rd option i saw but i found majority of the time this is being used on app where we have a tab.



    无论是否使用Tab /底部导航栏,您仍然可以将这种方法用于所需的内容。

    PageViewClass
    class Home extends StatefulWidget {
    @override
    _HomeState createState() => _HomeState();
    }

    class _HomeState extends State<Home> with SingleTickerProviderStateMixin{
    PageController _pageController;

    @override
    void initState() {
    super.initState();
    _pageController = PageController();
    }

    @override
    void dispose() {
    super.dispose();
    _pageController?.dispose();
    }

    @override
    Widget build(BuildContext context) {
    return SafeArea(
    child: PageView(
    controller: _pageController,
    physics: NeverScrollableScrollPhysics(), // so the user cannot scroll, only animating when they select an option
    children: <Widget>[
    Dashboard(playingId: 1, key: PageStorageKey<String>('MyPlayList'), pageController: _pageController), //or the name you want, but you need to give them a key to all the child so it can save the Scroll Position
    ListPage(appname: "FirstButton",playingId: 1, key: PageStorageKey<String>('FirstButton'), pageController: _pageController),
    ListPage(appname: "SecondButton",playingId: 1, key: PageStorageKey<String>('SecondButton'), pageController: _pageController),
    ListPage(appname: "ThirdButton",playingId: 1, key: PageStorageKey<String>('ThirdButton'), pageController: _pageController),
    ListPage(appname: "FourthButton",playingId: 1, key: PageStorageKey<String>('FourthButton'), pageController: _pageController)
    ],
    ),
    )
    );
    }
    }

    现在,您将PageController传递给所有子项(向屏幕1和2添加键和PageController属性),在DashBoard(屏幕1)中,您可以将按钮的onTap从MaterialRoute更改为
    onTap: () => widget.pageController.jumpToPage(x), //where x is the index of the children of the PageView you want to see (between 0 and 4 in this case)

    在屏幕2中,用WillPopScope包装所有的脚手架,这样当用户点按而不是关闭路线时,它会回到索引0处的Dashboard Widget。
    @override
    Widget build(BuildContext context) {
    return WillPopScope(
    onWillPop: () {
    widget.pageController.jumpToPage(0); // Move back to dashboard (index 0)
    return false;
    }
    child: Scaffold(...)
    );

    }

    如果需要一些效果,例如动画(animateTo,nextPage,previousPage等),则可以使用PageController的其他方法。

    关于flutter - 如何在Flutter中重新访问时保存页面状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62108798/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com