0

我是 Flutter 和 graphql 的新手我正在尝试开发一个应用程序以在开发期间使用托管在 heroku 上的后端 api,并且在我的三星 Note 5 上测试该应用程序时,该应用程序成功连接到后端,我可以从查询中获取数据和突变,但是在构建 app-release.apk 并将其安装在同一移动设备上之后,查询和突变的响应始终为空。此外,我在后端有 REST api,我使用 Dio lib 发送请求,但我没有从这些请求中得到任何响应。我尝试了“flutter clean”,但徒劳地颤动医生命令显示没有错误:

Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 2.0.3, on Microsoft Windows [Version 10.0.18363.1646], locale en-US)
[√] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[√] Chrome - develop for the web
[√] Android Studio
[√] VS Code (version 1.54.3)
[√] Connected device (2 available)

• No issues found!

我正在使用安卓工作室 4.2.2

main.dart

bool isAuth;

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await initHiveForFlutter();
  isAuth = await isAuthenticated();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GraphQLProvider(
      client: client,
      child: MaterialApp(
          debugShowCheckedModeBanner: false,
          title: 'Flutter App',
          theme: ThemeData(
            primarySwatch: Colors.red,
          ),
          initialRoute: isAuth ? 'HomeScreen' : 'LoginScreen',
          routes: {
            'HomeScreen': (context) => HomeScreen(),
            'LoginScreen': (context) => LoginScreen()
          }),
    );
  }
}

身份验证.dart

// check if token is set using sharedPreferences lib
Future<bool> isAuthenticated() async {
  final accessToken = await getAccessToken(); 
  if (accessToken != null) {
    return true;
  }
  return false;
}

GraphQLConfiguration.dart:

class GraphQLConfiguration {

  HttpLink _httpLink;
  AuthLink _authLink;
  Link _link;

  GraphQLConfiguration () {
    _httpLink = new HttpLink('https://backendapi.herokuapp.com/graphql');
    _authLink = new AuthLink(getToken: () async => 'Bearer ${await getAccessToken()}');
    _link = _authLink.concat(_httpLink);
  }

  GraphQLClient myGQLClient() {
    return GraphQLClient(
      link: _link,
      cache: GraphQLCache(store: HiveStore()),
    );
  }
}
ValueNotifier<GraphQLClient> client = ValueNotifier(GraphQLConfiguration().myGQLClient());

突变.dart

String login() {
    return '''
      mutation login(\$data: LoginInput!){
        login(data: \$data){
          status
          message
          accessToken
        } 
      }
    ''';
  }

登录界面.dart


class LoginScreen extends StatefulWidget {
  @override
  _LoginScreenState createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {
  bool _hidePassword = true;

  final TextEditingController _usernameController = TextEditingController();
  final TextEditingController _passwordController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: false,
      body: Stack(
        children: [
          Mutation(
            options: MutationOptions(
                document: gql(mutations.login()),
                update: (GraphQLDataProxy cache, QueryResult result) {
                  String cookie;
                  final String cookieHeader = result.context
                      .entry<HttpLinkResponseContext>()
                      .headers['set-cookie'];
                  if (cookieHeader != null) {
                    cookie = cookieHeader.split(';')[0];
                  }

                  final LoginResponse loginResponse =
                      LoginResponse.from(result.data['login']);

                  if (loginResponse.status == true && cookie != null) {
                    setRefreshToken(cookie);
                  }
                  return cache;
                },
                onCompleted: (resultData) async {
                  final LoginResponse loginResponse =
                      LoginResponse.from(resultData['login']);
                  if (loginResponse.status == true) {
                    await setAccessToken(loginResponse.accessToken);
                    Navigator.pushReplacement(context,
                        MaterialPageRoute(builder: (context) => HomeScreen()));
                  }
                  Fluttertoast.showToast(
                    msg: loginResponse.message,
                    backgroundColor: Colors.grey,
                    gravity: ToastGravity.BOTTOM,
                    fontSize: 16.0,
                    timeInSecForIosWeb: 1,
                    textColor: Colors.white,
                    toastLength: Toast.LENGTH_LONG,
                  );
                }),
            builder: (RunMutation runMutation, QueryResult result) {
              return Column(
                mainAxisSize: MainAxisSize.max,
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  Container(
                    margin: EdgeInsets.only(top: 100),
                    child: Column(
                      children: [
                        Text(
                          'Welcome...',
                          style: TextStyle(
                            shadows: [
                              Shadow(
                                offset: Offset(0.5, 0.5),
                                blurRadius: 10.0,
                                color: Colors.grey,
                              ),
                            ],
                            fontSize: 45,
                            letterSpacing: 2,
                            fontWeight: FontWeight.bold,
                          ),
                        ),
                        Text(
                          'welcome,,,',
                          style: TextStyle(
                            fontSize: 20,
                            letterSpacing: 7,
                          ),
                        )
                      ],
                    ),
                  ),
                  Container(
                    child: Column(
                      children: [
                        Padding(
                          padding:
                              EdgeInsets.symmetric(vertical: 0, horizontal: 20),
                          child: TextField(
                            controller: _usernameController,
                            style: TextStyle(
                              fontSize: 22.0,
                            ),
                            decoration: InputDecoration(
                              labelText: 'Username',
                              border: OutlineInputBorder(
                                borderRadius: BorderRadius.circular(50.5),
                              ),
                              prefixIcon:
                                  Icon(Icons.supervised_user_circle_outlined),
                            ),
                          ),
                        ),
                        Padding(
                          padding: EdgeInsets.symmetric(
                              vertical: 10, horizontal: 20),
                          child: TextField(
                            controller: _passwordController,
                            obscureText: _hidePassword,
                            style: TextStyle(
                              fontSize: 22.0,
                            ),
                            decoration: InputDecoration(
                              labelText: 'Password',
                              border: OutlineInputBorder(
                                borderRadius: BorderRadius.circular(50.5),
                              ),
                              prefixIcon: Icon(Icons.lock),
                              suffixIcon: IconButton(
                                icon: Icon(_hidePassword
                                    ? Icons.visibility
                                    : Icons.visibility_off),
                                onPressed: () => _togglePasswordVisibility(),
                              ),
                            ),
                          ),
                        ),
                        Padding(
                          padding: EdgeInsets.only(top: 30),
                          child: ElevatedButton(
                            style: ButtonStyle(
                              padding: MaterialStateProperty.all<EdgeInsets>(
                                  EdgeInsets.all(15)),
                              minimumSize:
                                  MaterialStateProperty.all<Size>(Size(370, 0)),
                              shape: MaterialStateProperty.all<
                                  RoundedRectangleBorder>(
                                RoundedRectangleBorder(
                                  borderRadius: BorderRadius.circular(50.0),
                                  side: BorderSide(color: Colors.red),
                                ),
                              ),
                              backgroundColor:
                                  MaterialStateProperty.all<Color>(Colors.red),
                            ),
                            onPressed: () => runMutation(
                              {
                                'data': {
                                  'username': _usernameController.text,
                                  'password': _passwordController.text
                                }
                              },
                            ),
                            child: Text(
                              'Login',
                              style: TextStyle(
                                fontSize: 30.0,
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                  Container(
                    margin: EdgeInsets.only(top: 100),
                    padding: EdgeInsets.only(bottom: 20),
                    child: Center(
                      child: Text(
                        'BY XXX',
                        style: TextStyle(
                          color: Colors.grey,
                          fontWeight: FontWeight.bold,
                          fontSize: 10,
                        ),
                      ),
                    ),
                  ),
                ],
              );
            },
          ),
        ],
      ),
    );
  }

  void _togglePasswordVisibility() {
    setState(() {
      _hidePassword = !_hidePassword;
    });
  }

发布规范.yaml


environment:
  sdk: ">=2.7.0 <3.0.0"

dependencies:
  flutter:
    sdk: flutter
  graphql_flutter: ^5.0.0
  shared_preferences: ^2.0.6
  http: ^0.13.3
  fluttertoast: ^8.0.7
  font_awesome_flutter: ^9.1.0
  dio: ^4.0.0
  flutter_datetime_picker: ^1.5.1
  loading_overlay: ^0.3.0

  cupertino_icons: ^1.0.2


dev_dependencies:
  flutter_test:
    sdk: flutter

flutter:

  uses-material-design: true


  assets:
     - assets/images/male.png
     - assets/images/female.png

  fonts:
    - family: Changa
      fonts:
        - asset: fonts/Changa-Regular.ttf
        - asset: fonts/Changa-Bold.ttf
          weight: 700

4

1 回答 1

0

正如我所说,我是颤振和移动应用程序开发的新手,解决方案是从这个线程获得的

该问题与flutter_graphql lib无关,而是与android项目的清单文件有关。应声明互联网许可。我以为 Flutter 会根据使用的库自动检测和配置应用程序权限,但我错了。

于 2021-07-14T18:32:09.157 回答