Использование общих настроек в initState виджета вызывает ошибку

#flutter #sharedpreferences #flutter-sharedpreference

#flutter #sharedpreferences #flutter-sharedpreference

Вопрос:

Я хочу отобразить значение, сохраненное в ключе объекта класса SharedPreference в панели приложений, в виде текста, для которого я должен объявить следующий код в initState виджета.

 initState() {
    // TODO: implement initState
    super.initState();
    debugPrint("Runed");
    _getPrefs();
    SharedPreferences.getInstance().then((prefs) {
      setState(() => prefs = prefs);
    });
    
  }
 

Мой код _getPrefs() выглядит следующим образом:

  SharedPreferences prefs;

  Future<dynamic> _getPrefs() async {
    prefs = await SharedPreferences.getInstance();
    return prefs;
  }
 

и мой код панели приложений таков:

 appBar: AppBar(
        title: Text(prefs.getString("username")),
        centerTitle: true,
      ),
 

Тело виджета:

   body: ListView(
        children: [
          FutureBuilder(
              future: _getPrefs(),
              builder: (context, snapshot) {
                if (snapshot.hasData) {
                  return Column(
                    mainAxisAlignment: MainAxisAlignment.start,
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: <Widget>[
                      Padding(
                        padding: EdgeInsets.only(left: 5, top: 5, right: 5),
                        child: Container(
                          width: double.infinity,
                          padding: EdgeInsets.only(left: 5),
                          decoration: BoxDecoration(
                            color: Colors.white54,
                            shape: BoxShape.rectangle,
                            borderRadius: BorderRadius.circular(25.0),
                            boxShadow: [
                              BoxShadow(blurRadius: 2, color: Colors.white)
                            ],
                          ),
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: <Widget>[
                              Container(
                                width: 100,
                                height: 100,
                                margin: EdgeInsets.only(
                                    top: 3, left: 10, bottom: 10),
                                decoration: BoxDecoration(
                                  color: Colors.white,
                                  shape: BoxShape.circle,
                                  image: DecorationImage(
                                      image: NetworkImage(
                                          prefs.getString("photoUrl")),
                                      fit: BoxFit.fill),
                                ),
                              ),


                              Column(
                                crossAxisAlignment: CrossAxisAlignment.start,
                                children: [
                                  Text(
                                    prefs.getString("username"),
                                    style: TextStyle(
                                        fontSize: 22,
                                        color: Colors.black45,
                                        fontWeight: FontWeight.bold),
                                  ),
                                  Text(prefs.getString("email"))
                                ],
                              ),


                              /*  Text(
                            prefs.getString("email").toString(),
                            style: TextStyle(fontSize: 18, color: Colors.white70),
                          )*/
                            ],
                          ),
                        ),
                      ),
                    ],
                  );
                } else {
                  return Center(child: Text('False'));
                }
              }),
        ],
      ),
 

Я успешно получаю результаты при переходе с одного экрана на экран, на котором я хочу отобразить текст в панели приложений, но в консоли отображается какая-то ошибка, которая раздражает. Пожалуйста, помогите, сообщив причину и решение! Ошибка в консоли заключается в следующем:

 Reloaded 14 of 873 libraries in 3,092ms.
I/flutter (20249): Runed

════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following NoSuchMethodError was thrown building ProfileDetail(dirty, state: _ProfileDetailState#6aebe):
The method 'getString' was called on null.
Receiver: null
Tried calling: getString("username")

The relevant error-causing widget was: 
  ProfileDetail file:///D:/All Data/My Projects/Mine Created Flutter Projects/food_delivery_app/lib/main.dart:268:53
When the exception was thrown, this was the stack: 
#0      Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
#1      _ProfileDetailState.build (package:food_delivery_app/ProfileDetails/profileDetail.dart:36:27)
#2      StatefulElement.build (package:flutter/src/widgets/framework.dart:4744:28)
#3      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4627:15)
#4      StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4800:11)
...
════════════════════════════════════════════════════════════════════════════════════════════════════
 

Комментарии:

1. вы помещаете строку username в Text("") ?

2. Ваш код избыточен. Вы дважды запускали SharedPreferences.getInstance(). В этом сценарии вам придется использовать FutureBuilder. Дождитесь, пока SharedPreferences вернет имя пользователя, а затем отобразит его в текстовом виджете. Это видео поможет вам: youtube.com/watch?v=ek8ZPdWj4Qo и взгляните на это: medium.com/flutterworld /…

3. Ну, я использовал future builder в теле scaffol, но не смог использовать Future builder в панели приложений, поэтому использовал этот фрагмент кода « SharedPreferences.getInstance().then((prefs) { setState(() => prefs = prefs); });« в initStateметод. Я также обновляю свой вопрос с телом виджета.

Ответ №1:

Проблема в том, что SharedPreferences.getInstance это асинхронно, но вы вызываете его в методе синхронизации, где вы не можете await . Следовательно, ваш AppBar создается до SharedPreferences.getInstance возврата, то prefs есть null .

Простое решение — проверить значение null prefs и возвращать пустую строку или строку по умолчанию, пока setState не будет вызвано значение, отличное от null prefs .

 appBar: AppBar(
  title: Text(prefs?.getString("username") ?? ''),
  centerTitle: true,
),