可能是因为前端请求的 API 接口返回的数据格式与前端解析数据的方式不匹配导致的空白页。建议检查一下后端返回的数据格式和前端解析数据的方式是否一致,并查看网络请求是否成功。同时,可以在前端代码中添加一些错误处理逻辑,如显示错误信息等,便于定位问题。

以下是前端代码示例,其中使用了 'dart:convert'、'package:flutter/material.dart'、'package:http/http.dart' 和 'package:dio/dio.dart' 库:

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:dio/dio.dart';

//以卡片形式展示
void main() {
  runApp(Myapp());
}

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

  @override
  State<Myapp> createState() => _MyappState();
}

class _MyappState extends State<Myapp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'test',
      home: Scaffold(body: FundsList()),
    );
  }
}

class Fund {
  String id;
  String name;
  String type;
  String? d1;
  String? d2;
  String? d3;
  String? d4;
  String? d5;

  String? d1_r;
  String? d2_r;
  String? d3_r;
  String? d4_r;
  String? d5_r;

  Fund({
    required this.id,
    required this.name,
    required this.type,
    this.d1,
    this.d2,
    this.d3,
    this.d4,
    this.d5,

    this.d1_r,
    this.d2_r,
    this.d3_r,
    this.d4_r,
    this.d5_r,
  });

  factory Fund.fromJson(Map<String, dynamic> json) {
    return Fund(
        id: json['id'],
        name: json['name'],
        type: json['type'],
        d1: json['d1'],
        d2: json['d2'],
        d3: json['d3'],
        d4: json['d4'],
        d5: json['d5'],
        d1_r: json['d1_r'],
        d2_r: json['d2_r'],
        d3_r: json['d3_r'],
        d4_r: json['d4_r'],
        d5_r: json['d5_r'],
    );
  }
}

class FundsList extends StatefulWidget {
  @override
  _FundsListState createState() => _FundsListState();
}

String addLineBreaks(String text) {
  if (text == null) {
    return '';
  }
  var formatted = text.replaceAll(',', ',
');
  return formatted;
}

TextSpan buildColoredTextSpan(String text, Color positiveColor, Color negativeColor,
    {bool shouldBreakLine = true, bool colorText = true}) {
  if (text == null) {
    text = 'null';
  }
  var number = double.tryParse(text);
  var isPositive = number != null && number > 0;
  var style = TextStyle(color: isPositive ? positiveColor : negativeColor);

  if (!colorText) {
    style = TextStyle(color: Colors.black);
  }

  var formatted = shouldBreakLine ? addLineBreaks(text) : text;

  return TextSpan(
    text: formatted,
    style: style,
  );
}

class _FundsListState extends State<FundsList> {
  List<Fund> _funds = [];
  bool _isLoadingMore = false;
  int _currentPage = 1;
  ScrollController _scrollController = ScrollController();

  Future<void> _getFunds() async {
    try {
      Response response = await Dio().get('http://172.21.74.112:5000/funds?page=1&per_page=10');
      print(response.data);
      print(response.data['funds']);
      List<dynamic> data = response.data['funds'];
      setState(() {
        _funds = data.map((fund) => Fund.fromJson(fund)).toList();
      });
    } catch (e) {
      print(e);
    }
  }

  Future<void> _loadMoreFunds() async {
    try {
      _isLoadingMore = true;
      _currentPage++;
      Response response = await Dio()
          .get('http://172.21.74.112:5000/funds?page=$_currentPage&per_page=10');
      List<dynamic> data = response.data['funds'];
      setState(() {
        _funds += data.map((fund) => Fund.fromJson(fund)).toList();
      });
    } catch (e) {
      print(e);
    } finally {
      _isLoadingMore = false;
    }
  }

  @override
  void initState() {
    super.initState();
    _getFunds();

    _scrollController.addListener(() {
      if (_scrollController.position.pixels ==
          _scrollController.position.maxScrollExtent) {
        _loadMoreFunds();
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Funds List'),
      ),
      body: ListView.builder(
        controller: _scrollController,
        itemCount: _funds.length + (_isLoadingMore ? 1 : 0),
        itemBuilder: (BuildContext context, int index) {
          if (index == _funds.length && _isLoadingMore) {
            return Center(
              child: CircularProgressIndicator(),
            );
          } else if (index == _funds.length) {
            return Container();
          }
          else {
            return Card(
              margin: EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
              child: Padding(
                padding: const EdgeInsets.all(16.0),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: <Widget>[
                    Text('基金代码:'+_funds[index].id),
                    Text(_funds[index].name),
                    Text(_funds[index].type),
                    RichText(
                      text: TextSpan(
                        children: [
                          TextSpan(text: '第一天:', style: TextStyle(color: Colors.black)),
                          buildColoredTextSpan('${_funds[index].d1 ?? 'null'}' ,Colors.red,  Colors.green,shouldBreakLine: false, colorText: true),
                          TextSpan(text: '第二天:', style: TextStyle(color: Colors.black)),
                          buildColoredTextSpan('${_funds[index].d2 ?? 'null'}', Colors.red,  Colors.green, shouldBreakLine: false, colorText: true),
                          TextSpan(text: '第三天:', style: TextStyle(color: Colors.black)),
                          buildColoredTextSpan('${_funds[index].d3 ?? 'null'}', Colors.red,  Colors.green, shouldBreakLine: false, colorText: true),
                          TextSpan(text: '第四天:', style: TextStyle(color: Colors.black)),
                          buildColoredTextSpan('${_funds[index].d4 ?? 'null'}', Colors.red,  Colors.green, shouldBreakLine: false, colorText: true),
                          TextSpan(text: '
第五天:', style: TextStyle(color: Colors.black)),
                          buildColoredTextSpan('${_funds[index].d5 ?? 'null'}', Colors.red,  Colors.green, shouldBreakLine: false, colorText: true),
                          TextSpan(text: '
第一天排名:${_funds[index].d1_r ?? 'null'}', style: TextStyle(color: Colors.black)),
                          TextSpan(text: '第二天排名:${_funds[index].d2_r ?? 'null'}', style: TextStyle(color: Colors.black)),
                          TextSpan(text: '第三天排名:${_funds[index].d3_r ?? 'null'}', style: TextStyle(color: Colors.black)),
                          TextSpan(text: '第四天排名:${_funds[index].d4_r ?? 'null'}', style: TextStyle(color: Colors.black)),
                          TextSpan(text: '第五天排名:${_funds[index].d5_r ?? 'null'}', style: TextStyle(color: Colors.black)),
                        ],
                      ),
                    ),
                    //下面是之前用的,没有判断正负号来决定颜色
                    // Text('第二天:'+(_funds[index].d2 ?? 'null')),
                    // Text('第三天:'+(_funds[index].d3 ?? 'null')),
                    // Text('第四天:'+(_funds[index].d4 ?? 'null')),
                    // Text('第五天:'+(_funds[index].d5 ?? 'null')),
                    SizedBox(height: 16.0), // 添加间隔
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        ElevatedButton(
                          style: ElevatedButton.styleFrom(
                            primary: Colors.green, // 按钮背景颜色
                            shape: RoundedRectangleBorder(
                              borderRadius: BorderRadius.circular(8.0), // 设置按钮圆角
                            ),
                          ),
                          onPressed: () {
                            print('Selected: ${_funds[index].name} - ${_funds[index].type} 打印自选');
                          },
                          child: Text('自选'),
                        ),
                        ElevatedButton(
                          style: ElevatedButton.styleFrom(
                            primary: Colors.red, // 按钮背景颜色
                            shape: RoundedRectangleBorder(
                              borderRadius: BorderRadius.circular(8.0), // 设置按钮圆角
                            ),
                          ),
                          onPressed: () {
                            print('Selected: ${_funds[index].name} - ${_funds[index].type} 打印买入');
                          },
                          child: Text('买入'),
                        ),
                        ElevatedButton(
                          style: ElevatedButton.styleFrom(
                            primary: Colors.blue, // 按钮背景颜色
                            shape: RoundedRectangleBorder(
                              borderRadius: BorderRadius.circular(8.0), // 设置按钮圆角
                            ),
                          ),
                          onPressed: () {
                            print('Selected: ${_funds[index].name} - ${_funds[index].type} 打印打印');
                          },
                          child: Text('打印'),
                        ),
                      ],
                    ),
                  ],
                ),
              ),
            );
          }
        },
      ),
    );
  }
}

以下是后端代码示例,使用了 'sqlalchemy' 和 'flask' 库,并通过 'flask_sqlalchemy' 连接数据库:

import sqlalchemy
from flask import Flask, jsonify, request
from flask_sqlalchemy import SQLAlchemy
#成功实现分页并展示基金
app = Flask(__name__)
app.config['JSON_AS_ASCII'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:3454123@localhost:3306/fund'  # 设置数据库URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

class Fund(db.Model):
    __tablename__='funds'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255))
    type = db.Column(db.String(255))
    d1 =db.Column(sqlalchemy.types.DECIMAL(precision=10, scale=2))
    d2 =db.Column(sqlalchemy.types.DECIMAL(precision=10, scale=2))
    d3 =db.Column(sqlalchemy.types.DECIMAL(precision=10, scale=2))
    d4 =db.Column(sqlalchemy.types.DECIMAL(precision=10, scale=2))
    d5 =db.Column(sqlalchemy.types.DECIMAL(precision=10, scale=2))
    d1_r=db.Column(db.Integer)
    d2_r=db.Column(db.Integer)
    d3_r=db.Column(db.Integer)
    d4_r=db.Column(db.Integer)
    d5_r=db.Column(db.Integer)



@app.route('/funds', methods=['GET'])
#下面的get_users代码普通展示基金表,没有按照单日排名什么的

# def get_users():
#     page = int(request.args.get('page', 1))
#     per_page = int(request.args.get('per_page', 10))
#     print(page,per_page)
#     funds = Fund.query.paginate(page=page, per_page=per_page, error_out=False)
#     result = {
#         'funds': [{'id': fund.id, 'name': fund.name, 'type': fund.type,
#                    'd1':fund.d1,'d2':fund.d2,'d3':fund.d3,'d4':fund.d4,'d5':fund.d5,
#                    'd1_r':str(fund.d1_r),'d2_r':str(fund.d2_r),'d3_r':str(fund.d3_r),'d4_r':str(fund.d4_r),'d5_r':str(fund.d5_r)
#                    } for fund in funds.items],
#         'total_pages': funds.pages,
#         'total_users': funds.total,
#         'current_page': funds.page,
#         'per_page': funds.per_page,
#         'has_prev': funds.has_prev,
#         'has_next': funds.has_next
#     }
#     return jsonify(result)

#以单日排名来排序的基金数据
def get_users():
    page = int(request.args.get('page', 1))
    per_page = int(request.args.get('per_page', 10))
    print(page, per_page)

    # 获取基金数据
    funds = Fund.query.paginate(page=page, per_page=per_page, error_out=False)

    # 计算每只基金的五日涨跌幅之和和平均涨跌幅
    for fund in funds.items:
        d_list = [fund.d1, fund.d2, fund.d3, fund.d4, fund.d5]
        total_d = sum(d_list)
        avg_d = total_d / 5
        setattr(fund, 'total_d', total_d)
        setattr(fund, 'avg_d', avg_d)

    # 对基金进行排序
    sorted_funds = sorted(funds.items, key=lambda x: x.total_d, reverse=True)

    result = {
        'funds': [{'id': fund.id,
                   'name': fund.name,
                   'type': fund.type,
                   'd1': fund.d1,
                   'd2': fund.d2,
                   'd3': fund.d3,
                   'd4': fund.d4,
                   'd5': fund.d5,
                   'd1_r': str(fund.d1_r),
                   'd2_r': str(fund.d2_r),
                   'd3_r': str(fund.d3_r),
                   'd4_r': str(fund.d4_r),
                   'd5_r': str(fund.d5_r),
                   'total_d': fund.total_d,
                   'avg_d': fund.avg_d
                   } for fund in sorted_funds],
        'total_pages': funds.pages,
        'total_users': funds.total,
        'current_page': funds.page,
        'per_page': funds.per_page,
        'has_prev': funds.has_prev,
        'has_next': funds.has_next
    }

    return jsonify(result)


if __name__ == '__main__':
    app.run(host='0.0.0.0',debug=True)

请确保前端代码中的 Fund.fromJson 方法与后端返回的数据格式相匹配。

如果仍然无法解决问题,可以尝试以下步骤:

  1. 使用浏览器开发者工具中的 Network 标签查看网络请求是否成功,以及后端返回的具体数据格式。
  2. 在前端代码中添加错误处理逻辑,例如捕获网络请求异常,并显示错误信息。
  3. 使用调试工具,例如 Flutter DevTools,进行代码调试,排查问题所在。

希望这些信息能帮助您解决问题。

Flutter 前端请求 API 接口渲染空白页问题排查指南

原文地址: https://www.cveoy.top/t/topic/nwR4 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录