Как правильно инициализировать построитель после получения значения общих настроек? - PullRequest
0 голосов
/ 10 июля 2020

Простой пример приложения с AppBar с двумя кнопками. Название приложения и главный экран меняются в зависимости от того, какую кнопку нажал пользователь.

Я покажу вам это с картинкой

экраны приложений

Я хочу сохранить это «состояние» значка в SharedPreferences, и всякий раз, когда пользователь снова открывает приложение, оно открывается с его последним активным выбором (To объясните себя лучше, если пользователь выберет значок «2», закроет приложение и снова откроет его, я хочу, чтобы оно открылось, как на скриншоте справа)

Я успешно выполнил все логи c за сохранением состояния, изменение заголовка и содержимого тела в зависимости от выбранного значка, но я не могу добиться автоматической проверки при запуске сохраненного значения, а затем создать макет в зависимости от этого ...

Это основной код этого экрана:

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class SimpleBooleanScreen extends StatefulWidget {
  @override
  SimpleBooleanScreenState createState() => new SimpleBooleanScreenState();
}

class SimpleBooleanScreenState extends State<SimpleBooleanScreen> {

  //Colors of the icons so one of them looks active and the other one inactive
  Color _firstIconColor = Colors.white;
  Color _secondIconColor = Colors.grey;

  //Global variable to check if the Screen One is active
  bool isScreenOneActive = true;

  //Key Name of the variable saved in shared preferences
  String keyName = "_updateScreenOneState";

  //THE FOLLOWING METHODS ARE RELATED TO SHARED PREFERENCES
  Future<bool> loadData() async {
    SharedPreferences preferences = await SharedPreferences.getInstance();
    return preferences.getBool(keyName) ?? true ;
  }
  Future<bool> saveData() async {
    SharedPreferences preferences = await SharedPreferences.getInstance();
    return preferences.setBool(keyName, isScreenOneActive);
  }
  setData() async {
    loadData().then((value){
      isScreenOneActive = value;
      setIconColors();
    });
  }

  //Check and set icon colors
  setIconColors() async {
    //Update the buttons with colour
    if(isScreenOneActive){
      _firstIconColor = Colors.white;
      _secondIconColor = Colors.grey;
    }
    else{
      _firstIconColor = Colors.grey;
      _secondIconColor = Colors.white;
    }
  }

  //INITIALIZE DATA
  @override
  void initState() {
    setData();
    super.initState();
  }

  //BUILD
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: 3,
        child: Scaffold(
          appBar: AppBar(
            backgroundColor: Color(0XFF01579B),
            actions: <Widget>[
              IconButton(
                icon: Icon( Icons.filter_1, size: 40.0, color: _firstIconColor,),
                onPressed: () {
                  setState(() {
                    //Change the colors and the global variable to true
                    isScreenOneActive = true;
                    setIconColors();
                    saveData(); //Updating the Shared Preferences value with the state of isScreenOneActive
                  });
                },
              ),
              IconButton(
                icon: Icon( Icons.filter_2,  color: _secondIconColor, size: 40.0,),
                onPressed: () {
                  setState(() {
                    //Change the color and the global variable to false
                    isScreenOneActive = false;
                    setIconColors();
                    saveData(); //Updating the Shared Preferences value with the state of isScreenOneActive
                  });
                },
              ),
            ],
            title: AppBarText(isScreenOnePassedActive: isScreenOneActive),
          ),
          body: MainBodyView(isScreenOnePassedActive: isScreenOneActive),
        ),
      ),
    );
  }
}

//Create text of the App Bar depending on the icon selected
class AppBarText extends StatelessWidget {
  const AppBarText({Key key, this.isScreenOnePassedActive}) : super(key: key);
  final bool isScreenOnePassedActive;

  @override
  Widget build(BuildContext context) {
    if (isScreenOnePassedActive) {
      return Text(
        'SCREEN ONE TITLE',
      );
    }
    else {
      return Text(
        'SCREEN TWO TITLE',
      );
    }
  }
}

//Create different Tabs depending on the icon selected
class MainBodyView extends StatelessWidget {
  const MainBodyView({Key key, this.isScreenOnePassedActive}) : super(key: key);
  final bool isScreenOnePassedActive;

  @override
  Widget build(BuildContext context) {
    if (isScreenOnePassedActive) {
      return Scaffold(
        body: Center(
          child: Text('SCREEN ONE',  style: TextStyle(fontSize: 20.0)),
        ),
      );
    }
    else {
      return Scaffold(
        body: Center(
          child: Text('SCREEN TWO',  style: TextStyle(fontSize: 20.0)),
        ),
      );
    }
  }
}

Прямо сейчас он сначала создает весь построитель (вкладки и все остальное), а ПОСЛЕ этого он обновляет значение

isScreenOneActive

с помощью метода вызывается здесь:

@override
void initState() {
  setData();
  super.initState();
}

В идеале эта переменная должна быть инициализирована следующим образом:

//Global variable to check if the UPDATE icon (first one) is active
bool isScreenOneActive= fetchScreenStatusPreference() ;

//Key Name of the variable saved in shared preferences
String keyName = "_updateScreenOneState"; 

fetchScreenStatusPreference()async{
  SharedPreferences preferences = await SharedPreferences.getInstance();
  return preferences.getBool(keyName) ?? true ;
}

Но это не работает, поскольку в нем говорится: «Только члены stati c могут быть доступ d в инициализаторах. "

Есть идеи обходного пути или как это правильно сделать?

Спасибо !!!

1 Ответ

0 голосов
/ 10 июля 2020

Только понял, почему ... Я забыл добавить setState () внутри метода setData ().

setData() async {
    loadData().then((value){
      setState(() {
        isScreenOneActive = value;
        setIconColors();
      });
    });
  }
...