Flutter 提供商个人资料图片未更新

Flutter provider profile picture not updating

我正在构建一种方法,用户可以使用 provider 包 select 喜欢的个人资料图片在应用程序周围显示。我使用 shared_preferences 在本地将个人资料图片首选项保存为 int 值。它起作用了,这意味着我可以将个人资料图片保存到本地系统。但问题是,provider 包在这种情况下完全变得无用,因为我必须将小部件转换为 statefull 并在插入 [=21= 时调用 setState 方法] 小部件树中的小部件。甚至 HomeScreen 中的 profilePicture 小部件也不会以这种方式更新。我想知道如何使用 provider 包来解决这个问题,而不是使用 statefulWidgets.

观看 Gif 或 video

这是我创建的提供者class:

class ProfilePicProvider with ChangeNotifier {
  ProfilePicPref profilePicPreferences = ProfilePicPref();
  int _svgNumber = 1;

  int get svgNumber => _svgNumber;

  set svgNumber(int value) {
    _svgNumber = value;
    profilePicPreferences.setProfilePic(value);
    notifyListeners();
  }

  void changePic(int val) {
    _svgNumber = val;
    profilePicPreferences.setProfilePic(val);
    notifyListeners();
  }
}

这是 sharedPreferences class

class ProfilePicPref {
  static const PRO_PIC_STS = 'PROFILESTATUS';

  setProfilePic(int svgNo) async {
    SharedPreferences profilePref = await SharedPreferences.getInstance();
    profilePref.setInt(PRO_PIC_STS, svgNo);
  }

  Future<int> getProfilePicture() async {
    SharedPreferences profilePref = await SharedPreferences.getInstance();
    return profilePref.getInt(PRO_PIC_STS) ?? 1;
  }
}

这是图像 selection 屏幕并将该数据保存到 sharedPreferences class

class SelectProfilePicture extends StatefulWidget {
  const SelectProfilePicture({Key? key}) : super(key: key);

  @override
  State<SelectProfilePicture> createState() => _SelectProfilePictureState();
}

class _SelectProfilePictureState extends State<SelectProfilePicture> {
  int svgNumber = 1;

  ProfilePicProvider proProvider = ProfilePicProvider();
  @override
  void initState() {
    getCurrentProfilePicture();

    super.initState();
  }

  void getCurrentProfilePicture() async {
    proProvider.svgNumber =
        await proProvider.profilePicPreferences.getProfilePicture();
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
        
          CurrentAccountPicture(
              path: 'assets/svg/${proProvider.svgNumber}.svg'),
          
          Expanded(
            child: GridView.builder(
              itemCount: 15,
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 3,
               
              ),
              itemBuilder: (context, index) {
                return GestureDetector(
                  onTap: () {
                    setState(() {
                     svgNumber = index + 1;
                    });
                    proProvider.changePic(index + 1);
                    proProvider.svgNumber = index + 1;
                  },
                  child: SvgPicture.asset('assets/svg/${index + 1}.svg'),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

这是 HomeScreen,无论是 statefull 还是 stateless

都不会更新个人资料图片
class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    
    final proPicProvider = Provider.of<ProfilePicProvider>(context);
    return Scaffold(
     body: 
      Column(
         children: [
          Row(
            children: [
               CurrentAccountPicture(
                      path: 'assets/svg/${proPicProvider.svgNumber}.svg'),
             ],
          ),
        ],
      ),
    );
  }
}

示例:

我必须将小部件转换为有状态并调用 setState 方法以从 sharedPreferences 获取当前个人资料图片。您可以从我提供的 GIF 中找到此屏幕。

class Progress extends StatefulWidget {
  const Progress({Key? key}) : super(key: key);

  @override
  State<Progress> createState() => _ProgressState();
}

class _ProgressState extends State<Progress> {

  ProfilePicProvider proProvider = ProfilePicProvider();

  @override
  void initState() {
    getCurrentProfilePicture();
    super.initState();
  }

  void getCurrentProfilePicture() async {
    proProvider.svgNumber =
        await proProvider.profilePicPreferences.getProfilePicture();
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: SizedBox(
                  height: 130.0,
                  width: 130.0,
                  child: SvgPicture.asset(
                      'assets/svg/${proProvider.svgNumber}.svg'),
        ),
      ),
    );
  }
}

当您创建 ChangeNotifier 的新实例时,问题出在 _SelectProfilePictureState 中: ProfilePicProvider proProvider = ProfilePicProvider();。这意味着您不是在整个上下文中使用可用的提供程序,而是每次都创建一个新的提供程序。因此,当您的提供者的值更改时,它仅在 _SelectProfilePictureState 内有效。您必须始终使用上下文调用它,而不是创建新实例:

class SelectProfilePicture extends StatefulWidget {
  const SelectProfilePicture({Key? key}) : super(key: key);

  @override
  State<SelectProfilePicture> createState() => _SelectProfilePictureState();
}

class _SelectProfilePictureState extends State<SelectProfilePicture> {
  int svgNumber = 1;

  // [removed] ProfilePicProvider proProvider = ProfilePicProvider();

  //removed
  /*void getCurrentProfilePicture() async {
    proProvider.svgNumber =
        await proProvider.profilePicPreferences.getProfilePicture();
    setState(() {});
  }*/

  @override
  Widget build(BuildContext context) {
    //use provider from the context
    final proProvider = Provider.of<ProfilePicProvider>(context,listen:true);
    return Scaffold(
      body: Column(
        children: [
        
          CurrentAccountPicture(
              path: 'assets/svg/${proProvider.svgNumber}.svg'),
          
          Expanded(
            child: GridView.builder(
              itemCount: 15,
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 3,
               
              ),
              itemBuilder: (context, index) {
                return GestureDetector(
                  onTap: () {
                    setState(() {
                     svgNumber = index + 1;
                    });
                    proProvider.changePic(index + 1);
                    proProvider.svgNumber = index + 1;
                  },
                  child: SvgPicture.asset('assets/svg/${index + 1}.svg'),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

如果您进入应用程序,您可能希望将最初选择的图像发送给您的提供商:

在ProfilePicProvider的构造函数中添加参数:

ProfilePicProvider(SharedPreferences prefs): _svgNumber = prefs.getInt(ProfilePicPref.PRO_PIC_STS) ?? 1;

在main.dart中:

    Future<void> main()async{
    WidgetsFlutterBinding.ensureInitialized();
    var prefs = await SharedPreferences.getInstance();

    runApp(
        MultiProvider(
      providers:[
        ChangeNotifierProvider( create:(_) => ProfilePicProvider(prefs))
      ],
      child: yourtopWidget
    )
   );

    }