How to make Flutter provider notifyListeners() from a factory?

Issue

I have a Provider of an Auth class. When the app loads, I call an API which returns json with data which I map into the Auth class using a factory method (Auth.fromJson). Once the mapping completes, I wish to notify listeners so that the relevant UI is updated. So it turns I cannot call notifyListeners() from the factory constructor because I get this error:

instance members cannot be accessed from a factory constructor

Why is this so? What workaround can I implement? After the factory maps data I need to be able to notifyListeners somehow.

class Auth with ChangeNotifier {
  String token;
  String organisationId;
  String domain;
  String userId;

  Auth(
      {this.token,
      this.organisationId,
      this.domain,
      this.userId});

  factory Auth.fromJson(Map<String, dynamic> json) {
    Auth(
      token: json['token'],
      organisationId: json['organisationId'],
      domain: json['domain'],
      userId: json['userId'],
    );
    notifyListeners(); // Error here. 
    return Auth();
  }
}

Solution

  1. factory methods are much like static methods. The way you can’t access class variables and methods applies to factory too.
  2. notifyListeners(); is a method of ChangeNotifier class and so you can’t access it through any static method or factory methods.
  3. You will need an instance of Auth to call notifyListeners();
  4. Better thing to do is to not to make Auth as ChangeNotifier if you really want to observe the change in Auth then make a ChangeNotifer that holds value of Auth. Following is the code for that.

import 'package:flutter/material.dart';

class Auth{
  String token;
  String organisationId;
  String domain;
  String userId;

  Auth(
      {this.token,
      this.organisationId,
      this.domain,
      this.userId});

  factory Auth.fromJson(Map<String, dynamic> json) {
    return Auth(
      token: json['token'],
      organisationId: json['organisationId'],
      domain: json['domain'],
      userId: json['userId'],
    ); 
  }
}

class AuthChangeNotifier  with ChangeNotifier {
  Auth auth;
  onNewAuth(Auth newAuth){
    this.auth = newAuth;
    notifyListeners();
  }
}
  1. You can also use ValueNotifier<Auth> for this use-case and observe it using ValueListenableBuilder<Auth>

Hope it helps, let me know if you have any doubts.

Answered By – Kalpesh Kundanani

Answer Checked By – Clifford M. (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *