Flutter: доступ к поставщику SharedPreferences / ChangeNotifier в классе Stream - PullRequest
0 голосов
/ 14 июля 2020

Я просмотрел StackoverFlow и не смог найти решение этой проблемы. Сценарий: у меня есть поставщик Flutter SharedPreferences с классом ChangeNotifier, который будет обновляться с учетом информации о текущем вошедшем в систему пользователе.

Упрощенное содержимое:

class SharedPreferences {
  final String userId;
  final String userName;

  SharedPreferences({
    @required this.userId,
    @required this.userName,
  });
}
class SharedPreferencesData with ChangeNotifier {
  var _sharedPreferencesData = SharedPreferences(
    userId: 'testUserId',
    userName: 'testUserName',
  );}

И файл database.dart с классом содержащий DataBaseServices для получения потоков FireStore из моментальных снимков:

class DatabaseService {
  final CollectionReference companiesProfilesCollection =
      Firestore.instance.collection('companiesProfiles');

  List<CompanyProfile> _companiesProfilesFromSnapshot(QuerySnapshot snapshot) {
    return snapshot.documents.map((doc) {
      return CompanyProfile(
        docId: doc.documentID,
        companyName: doc.data['companyName'] ?? '',
        maxLocationsNumber: doc.data['maxLocationsNumber'] ?? 0,
        maxUsersNumber: doc.data['maxUsersNumber'] ?? 0,
      );
    }).toList();
  }

  Stream<List<CompanyProfile>> get getCompaniesProfiles {
    return companiesProfilesCollection
        .where('userId', isEqualTo: _userIdFromProvider) 
        // My problem is above -----
        .snapshots()
        .map(_companiesProfilesFromSnapshot);
  }
}

Я не хочу извлекать все данные Stream, поскольку они могут быть огромными для других потоков, я просто хочу передать идентификатор пользователя в .where (' userId ', isEqualTo: _userIdFromProvider).

  • Мне не удалось получить доступ к контексту в этом классе, чтобы получить данные от поставщика

  • Не удалось 'не отправлять userId в геттер getCompaniesProfiles, так как геттер не принимает параметры

  • И если я конвертирую этот геттер в обычный метод, я не смогу отправить ему userID, так как это должно выполняться под void main () {runApp (MyApp ());} / return MultiProvider (provider: [] и к тому времени я не могу вызвать fetch sharedPreferences с контекстом, который не содержит информацию о поставщике ...

  • Не удалось понять, как получить контекст в качестве конструктора в этом классе, когда я это сделал, я получил следующее Только Доступ к членам stati c можно получить в инициализаторах в классе DatabaseService.

Я все еще новичок, поэтому был бы признателен, если бы вы поделились со мной лучшим подходом к обработке этот. Спасибо!

*********** Повторно отредактировано, добавив следующее: ************** Я пытаюсь реализовать то же самое сценарий, вот мой код: Основной файл:

return MultiProvider(
  providers: [
    ChangeNotifierProvider<SpData>(
      create: (context) => SpData(),
    ),
    ProxyProvider<SpData, DS>(
      create: (context) => DS(),
      update: (ctx, spData, previousDS) {
        print('ChangeNotifierProxyProvider RAN');
        previousDS.dbData = spData;
        return previousDS;
      },
    ),
  ],

SP-файл:

class SP {
  final String companyId;
  SP({
    @required this.companyId,
  });
}

class SpData with ChangeNotifier {
  var _sPData = SP(
    companyId: '',
  );
  void setCompanyId(String cpID) {
    final newSharedPreferences = SP(
      companyId: cpID,
    );
    _sPData = newSharedPreferences;
    print('_spData companyId:${_sPData.companyId}');
    notifyListeners();
  }

  String get getCompanyId {
    return _sPData.companyId;
  }
}

DS-файл:

class DS with ChangeNotifier {
  SpData dbData;
  void printCompanyId() {
    var companyId = dbData.getCompanyId;
    print('companyId from DataBase: $companyId');
  }
}

SpData dbData; внутри Class DS не обновляется. Я добавил распечатки, чтобы понять, что работает, а что нет. Когда я запускаю свой код, функция печати в файле main.dart print ('ChangeNotifierProxyProvider RAN'); не запускается.

Что мне не хватает? Почему ChangeNotifierProxyProvider не запускается для обновления dbData внутри файла DS? Спасибо!

1 Ответ

2 голосов
/ 14 июля 2020

Вы можете использовать ProxyProvider для этой цели.

ProxyProvider - провайдер, который строит значение на основе других провайдеров.

Вы сказали, что у вас есть MultiProvider, поэтому Я думаю, у вас есть провайдер SharedPreferencesData в этом MultiProvider, а затем DatabaseService провайдер. Что вам нужно сделать, так это использовать ProxyProvider для DatabaseService вместо обычного провайдера и основывать его на SharedPreferencesData провайдере.

Вот пример:

MultiProvider(
  providers: [
    ChangeNotifierProvider<SharedPreferencesData>(
      create: (context) => SharedPreferencesData(),
    ),
    ProxyProvider<SharedPreferencesData, DatabaseService>(
      create: (context) => DatabaseService(),
      update: (context, sharedPreferencesData, databaseService) {
        databaseService.sharedPreferencesData = sharedPreferencesData;
        return databaseService;
      },
      dispose: (context, databaseService) => databaseService.dispose(),
    ),
  ],
  child: ...

Здесь вот что происходит в приведенном выше фрагменте кода:

  1. ProxyProvider вызывает update каждый раз SharedPreferencesData изменения.
  2. DatabaseService получает свою sharedPreferencesData переменную, установленную внутри update.

Теперь, когда у вас есть доступ к sharedPreferencesData внутри экземпляра DatabaseService, вы можете легко делать то, что хотите.

...