Harald Wiesinger
Harald Wiesinger

Reputation: 681

Change ProfileImage in Drawer at runtime

I have a image in my Drawer sidemenu where the path to it is stored in a final object named userdata:

class MyDrawer extends StatelessWidget {
  MyDrawer({Key key, this.userdata}) : super(key: key);
  final User userdata;

  @override
  Widget build(BuildContext context) {
    return new Drawer(
      child: ListView(
        padding: EdgeInsets.zero,
        children: <Widget>[
          if (userdata != null) ...[
            DrawerHeader(
                decoration: BoxDecoration(color: Colors.green),
                child: Stack(children: <Widget>[
                  Align(
                      alignment: Alignment.centerLeft,
                      child: ClipOval(
                        child: userdata.image == '' || userdata.image == null
                            ? CircleAvatar(
                                radius: 50,
                                backgroundColor: Colors.white,
                                backgroundImage: AssetImage('assets/images/avatar.png'))
                            : Image.network(
                                userdata.image,
                                width: 100,
                                height: 100,
                                fit: BoxFit.cover,
                              ),
                      )),

When I am now on a page (profile.dart) where I can update my profile image (which is pushed by the drawer -sidemenu-)

How can I update the userdata object in the drawer class?

I found some ideas like streams, but is this really neccessary ?

edit: profile.dart

class ProfilePage extends StatefulWidget {
  @override
  _MyProfilePageState createState() => _MyProfilePageState();
}

class _MyProfilePageState extends State<ProfilePage> {
  final _formKey = GlobalKey<FormState>();
  final _username = TextEditingController();
  final _email = TextEditingController();
  final _firstname = TextEditingController();
  final _lastname = TextEditingController();
  final picker = ImagePicker();
  String image = '';

  @override
  void initState() {
    ProfileApi().getProfile().then((user) {
      setState(() {
        this._username.text = user.sId;
        this._email.text = user.email;
        this._firstname.text = user.firstname;
        this._lastname.text = user.lastname;
        this.image = user.image;
      });
    });
    super.initState();
  }

.....

  changeUser() async {
    try {
      User userdata = await ProfileApi().updateProfile(
          this._username.text, this._email.text, this._firstname.text, this._lastname.text);

    //call some function here to update userdata in my drawer  <--

      Fluttertoast.showToast(msg: 'Profile updated');
    } on Exception catch (error) {
      Fluttertoast.showToast(msg: error.toString());
      return;
    }
  }

i also have a storage class where the userdata object is also provided:

class UserStorage {
  Future<User> getUserData() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    String userdata = prefs.getString('userdata') ?? '';
    if (userdata != "") {
      dynamic user = json.decode(userdata);
      return User.fromJson(user);
    } else {
      return null;
    }
  }
}

Upvotes: 0

Views: 217

Answers (1)

dm_tr
dm_tr

Reputation: 4763

Keep your userData content in a global variable

globals.dart file

library globals;

ValueNotifier userDataNotifier = ValueNotifier(null);

Convert your MyDrawer class to StatefulWidget and remove the User variable inside it. Then use your variable in a ValueListenableBuilder widget

import 'globals.dart' as globals; // ...

class MyDrawer extends StatefulWidget {
  MyDrawer({Key key}) : super(key: key);

  @override
  _MyDrawerState createState() => _MyDrawerState();
}

class _MyDrawerState extends State<MyDrawer> {
  @override
  Widget build(BuildContext context) {
    return Drawer(
      //...
            Align(
              //...
              child: ValueListenableBuilder(
                valueListenable: globals.userDataNotifier,
                builder: (context, userdata, _) {
                  return ClipOval(
                    child: userdata.image == '' || userdata.image == null
                        ? CircleAvatar(
                        radius: 50,
                        backgroundColor: Colors.white,
                        backgroundImage: AssetImage('assets/images/avatar.png'))
                        : Image.network(
                      userdata.image,
                      width: 100,
                      height: 100,
                      fit: BoxFit.cover,
                    ),
                  );
                },
              ),
            ),
    );
  }
}

Finally in your changeUser function, simply change the content of your notifier

import 'globals.dart' as globals;
// ...


changeUser() async {
  try {
    User userdata = await ProfileApi().updateProfile(this._username.text, this._email.text, this._firstname.text, this._lastname.text);

    // simply change the content of userData
    globals.userDataNotifier = userdata;

    Fluttertoast.showToast(msg: 'Profile updated');
  } on Exception catch (error) {
    Fluttertoast.showToast(msg: error.toString());
    return;
  }
}

Upvotes: 1

Related Questions