简体   繁体   中英

Flutter with Riverpod is stuck in loading state

I'm coding on Login page with Riverpod, everything go fine but when user is try to login, system is stuck on loading state and didn't send data to data state. I don't know why.

my code is like this: login form -> login controller -> login repository, then send data back to login form and redirect to dashboard.

this code in login page

class LoginPage extends ConsumerWidget {
  LoginPage({Key? key}) : super(key: key);

  final TextEditingController usernameController = TextEditingController();
  final TextEditingController passwordController = TextEditingController();

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Padding(
      padding: const EdgeInsets.all(20),
      child: Container(
        decoration: BoxDecoration(borderRadius: BorderRadius.circular(20)),
        padding: const EdgeInsets.all(20),
        child: Column(
          children: [
            Image.asset(
              "assets/images/logo.png",
              width: 80,
            ),
            const SizedBox(
              height: 20,
            ),
            TextField(
              controller: usernameController,
              decoration: const InputDecoration(
                border: OutlineInputBorder(),
                labelText: 'Email / Username',
              ),
            ),
            const SizedBox(
              height: 20,
            ),
            TextField(
              controller: passwordController,
              obscureText: true,
              decoration: const InputDecoration(
                border: OutlineInputBorder(),
                labelText: 'Password',
              ),
            ),
            const SizedBox(
              height: 20,
            ),
            TextButton(
                onPressed: () {
                  final loginDataValue = ref.watch(loginControllerProvider({
                    "username": usernameController.text,
                    "password": passwordController.text
                  }));

                  loginDataValue.when(
                      data: (userData) {
                        if (userData["isLoggedIn"]) {
                          GoRouter.of(context).goNamed("home");
                        }
                      },
                      error: (e, __) => debugPrint(e.toString()),
                      loading: () => debugPrint("loading"));
                },
                child: const Text("Sign in"),
                style: TextButton.styleFrom(
                    backgroundColor: const Color.fromARGB(255, 105, 240, 233),
                    primary: Colors.black87,
                    minimumSize: const Size(88, 36),
                    padding: const EdgeInsets.symmetric(horizontal: 16.0)))
          ],
        ),
      ),
    );
  }
}

then, this is controller

import 'package:calendar/repositories/login_repository.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

class LoginController extends StateNotifier<AsyncValue<Map>> {
  LoginController(this._loginRepository,
      {required this.username, required this.password})
      : super(const AsyncValue.loading()) {
    login(username: username, password: password);
  }
  final LoginRepository _loginRepository;
  final String username;
  final String password;

  Future<void> login(
      {required String username, required String password}) async {
    try {
      state = const AsyncValue.loading();
      final suggestions = await _loginRepository.loginUser(
          username: username, password: password);
      state = AsyncValue.data(suggestions);
    } catch (err) {
      state = AsyncValue.error(err);
    }
  }
}

final loginControllerProvider = StateNotifierProvider.autoDispose
    .family<LoginController, AsyncValue<Map>, Map>((ref, data) {
  final loginRepository = ref.watch(loginRepositoryProvider);
  return LoginController(loginRepository,
      username: data["username"], password: data["password"]);
});

then, this is repository

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

class LoginRepository {
  Future<Map> loginUser(
      {required String username, required String password}) async {
    try {
      return {
        "username": username,
        "token": "tokenfromapi",
        "isLoggedIn": true
      };
    } catch (err) {
      throw AsyncValue.error(err);
    }
  }
}

final loginRepositoryProvider = Provider<LoginRepository>((ref) {
  return LoginRepository();
});

can anyone tell me, what is wrong?

thank you

Looks overly complicated, I would simplify a lot. Something like this:

final loginControllerProvider = FutureProvider.family<Map, Map>((ref, data) async {
  //TODO call login API
  return {
    "username": data["username"],
    "token": "tokenfromapi",
    "isLoggedIn": true
  };
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM