0

我一直在尝试制作一个应用程序,其中调用 api 并在已TextField
使用的提供程序中更新数据以进行状态管理,这是它的代码。

class ProfileProvider with ChangeNotifier {
  var profileData;
  String _url = "http://10.0.2.2:3000/api/v1/user/loggedin_user";

  void getData() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    var token = prefs.getString('token');
    var data = await http.get(
      _url,
      headers: {
        "accept": "application/json",
        "content-type": "application/json",
        'Token': token,
      },
    );
    var infoOfPerson = json.decode(data.body);
    profileData = new ProfileObject(
      name: infoOfPerson['name'],
      mobile: infoOfPerson['mobile'],
      email: infoOfPerson['email'],
      role: infoOfPerson['role'],
    );
    notifyListeners();
  }

  ProfileObject get profileInfo {
    return profileData;
  }
}

我得到的数据很好,现在我必须在 UI 中显示它,但有时会填充数据,有时不会。有人可以指出为什么会发生这种情况的正确方向。

这是 UI 的代码。

 class Profile extends StatefulWidget {
  @override
  _ProfileState createState() => _ProfileState();
}

class _ProfileState extends State<Profile> {
  final emailController = TextEditingController(text: '');
  final nameController = TextEditingController(text: '');
  final mobileController = TextEditingController(text: '');
  var _isInit = true;

  @override
  void didChangeDependencies() {
    if (_isInit) {
      final profileData = Provider.of<ProfileProvider>(context);
      profileData.getData();
      if (profileData.profileInfo != null) {
        emailController.text = profileData.profileInfo.name;
        nameController.text = profileData.profileInfo.email;
        mobileController.text = profileData.profileInfo.mobile;
      }
      _isInit = false;
      super.didChangeDependencies();
    }
  }

  @override
  Widget build(BuildContext context) {
    final profileData = Provider.of<ProfileProvider>(context);

    return Scaffold(
      drawer: NavigationDrawer(),
      body: profileData.profileInfo == null
          ? Center(
              child: CircularProgressIndicator(),
            )
          : Builder(
              builder: (context) => SingleChildScrollView(
                child: Padding(.....

在填充下方,有 normal TextField,有人可以告诉我为什么数据有时会被填充,有时它会变空,即使我用它包裹起来CircularProgressIndicator()并检查 它notifyListeners();在那里不起作用。加载程序未显示,数据未加载。

谢谢

4

1 回答 1

0

我创建了一个名为 nextTick 的函数,我在 initState 中调用它,它现在可以工作,但想看看其他方法

void nextTick(Function callback, [int milliseconds = 0]) {
  Future.delayed(Duration(milliseconds: 0)).then((_) {
    callback();
  });
}

然后像下面一样使用它

  @override
  void initState() {
    super.initState();
    nextTick((){
      ProfileProvider profileProvider = Provider.of<ProfileProvider>(context);
      profileProvider.getProfile();
    });
  }

编辑:我在 ui 上存储了几个变量来管理它们,比如 isLoading、hasError 和 errorMessage。这是我的提供者类

class ProfileProvider extends ChangeNotifier {
  bool _hasError = false;
  bool _isLoading = true;
  String _errorMsg = '';
  Profile _profileResponse;

  bool get hasError => _hasError;

  bool get isLoading => _isLoading;

  String get errorMsg => _errorMsg;

  Profile get profileResponse => _profileResponse;

  Future<void> getProfile() async {
    this.setLoading = true;
    this.setError = false;
    this.setErrorMsg = '';
    try {
      await dio.post('$api/p/view', data: {}).then((res) {
        print(res.data);
        _profileResponse = Profile.fromJson(jsonDecode(res.data));
        print(_profileResponse.data);
        notifyListeners();
      }).whenComplete(() {
        this.setLoading = false;
      });
    } catch (e) {
      this.setError = true;
      this.setErrorMsg = '$e';
    }
    this.setLoading = false;
  }


  set setError(bool val) {
    if (val != _hasError) {
      _hasError = val;
      notifyListeners();
    }
  }

  set setErrorMsg(String val) {
    if (val != null && val != '') {
      _errorMsg = val;
      notifyListeners();
    }
  }

  set setLoading(bool val) {
    _isLoading = val;
    notifyListeners();
  }
}
于 2019-12-26T11:10:56.290 回答