【问题标题】:How to Access Provider with out Context in FlutterFlutter 中如何在没有上下文的情况下访问 Provider
【发布时间】:2023-03-13 02:23:01
【问题描述】:

我对 Flutter Provider 模式有疑问,我需要从没有 Context 的 Class 访问 Provides。

提供者:

import 'package:flutter/foundation.dart';
class TokenProvider with ChangeNotifier {
  TokenService tokenService = TokenService();
  String _accessToken = '';

  String get accessToken {
    return _accessToken;
  }

  dynamic setAccessToken(data) async {

    _accessToken = data;

  }
}

类:


import '../constants/constants.dart';
import '../models/models.dart';
import './network-call/base-service.dart';

class TokenService extends BaseService {
  Future<String> getToken() async {
    final dynamic response = await serviceCall(
        url: ApiName().apiName(api: ServiceName.TOKEN),
        method: ApiMethod.POST,
        queryParameters: {
          'id': Preferences().env['id'],
          'secret': Preferences().env['secret'],
          'type': 'rrrr'
        });
Need to set this responce Data in Providers
  }

}

谢谢。

【问题讨论】:

  • 类是在提供者的create函数内部创建的吗?
  • Rémi 更新了内容。感谢您的快速回复。
  • 我相信您需要在实例化 TokenService 类时传递上下文,以便您可以使用提供的上下文访问提供程序

标签: flutter flutter-dependencies flutter-plugin


【解决方案1】:

我习惯在需要时传递上下文,正如 dlohani 在问题的评论中所建议的那样,但我发现自己处于相同的情况并应用了一个受隔离之间使用的通信模式启发的解决方案:消息交换。

Provider 类需要有一个ReceiverPort 字段来监听请求消息。消息到达此侦听器时,您位于 Provider 中,因此您可以检索数据并将其发送回,同样采用 ReceiverPort 的方式,即使用在请求类中注册的 ReceiverPort 的 sendPort。

在下面的代码中,我假设消息是Maps,以阐明交换的数据类型:

class SomeProvider with ChangeNotifier {
  var _innerData = yourData;
  var _providerReceiverPort = ReceiverPort();

  SomeProvider() {
    // The registration is necessary to "publish" the receiver port 
    IsolateNameServer.registerPortWithName(
      _providerReceiverPort, "SomeProviderPort");

    _providerReceiverPort.listen(
      (message) {
        // I retrieve the port to send the response to
        var port = message["sendPort"];
        // The answer follows the rules of messaging: maps and lists are ok
        port.send({"data": _innerData.getSomething()});
      }
    );
  }
}

class SomeClient {
  var _clientReceiverPort = ReceiverPort();
  
  someFunction(){
    // First step: prepare the receiver to obtain data
    _clientReceiverPort.listen(
      (message) {
        // Data are stored in the map containing a "data" key
        var response = message["data"];
        ...
      }
    );

    // Now I can retrieve the provider port by using the same name it uses to publish it
    var providerPort = IsolateNameServer.lookupPortByName("SomeProviderPort");
    // The message must include the sendPort to permit the provider to address the response
    providerPort.send({"sendPort": _clientReceiverPort.sendPort});
  }
}

这个解决方案的缺点是 Provider 不能作为 SomeClient 类的提供者。如果侦听器中的任何更改对订阅者很重要,您显然可以通知:例如,我使用此模式从后台隔离更新提供程序中的数据。

正如我所说,这是一种解决方法,欢迎提出任何改进建议。

【讨论】:

    【解决方案2】:

    尝试添加“notifyListeners();”

      dynamic setAccessToken(data) async {
    
        _accessToken = data;
        notifyListeners();
      }
    

    【讨论】:

      猜你喜欢
      • 2018-10-02
      • 2012-07-01
      • 2011-07-31
      • 1970-01-01
      • 2021-03-20
      • 2020-10-28
      • 2022-09-29
      • 2014-12-30
      • 1970-01-01
      相关资源
      最近更新 更多