Flutter 错误:异常:无法加载 sertifikasi:类型“String”不是索引的“int”类型的子类型

问题描述 投票:0回答:1

这是我的代码

import 'package:flutter/material.dart';
import 'package:mobile_smarcerti/app/modules/sertifikasi/views/detail_sertifikasi_body.dart';
import 'package:mobile_smarcerti/app/modules/sertifikasi/views/detail_sertifikasi_page.dart';
import 'package:mobile_smarcerti/pages/upload_sertifikasi_dosen.dart';
import 'package:mobile_smarcerti/services/api_service.dart';

class SertifikasiBody extends StatefulWidget {
  const SertifikasiBody({super.key});

  @override
  __SertifikasiScreenState createState() => __SertifikasiScreenState();
}

class __SertifikasiScreenState extends State<SertifikasiBody> {
  late Future<List<dynamic>> _sertifikasiFuture;

  @override
  void initState() {
    super.initState();
    _sertifikasiFuture = ApiService().fetchSertifikasi();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          children: [
            Row(
              children: [
                Expanded(
                  child: TextField(
                    decoration: InputDecoration(
                      hintText: 'Search',
                      prefixIcon: const Icon(Icons.search),
                      border: OutlineInputBorder(
                        borderRadius: BorderRadius.circular(12),
                      ),
                      fillColor: const Color.fromARGB(145, 255, 249, 249),
                      filled: true,
                    ),
                  ),
                ),
                const SizedBox(width: 10),
                Container(
                  height: 54,
                  width: 48,
                  decoration: BoxDecoration(
                    color: const Color.fromARGB(145, 255, 249, 249),
                    borderRadius: BorderRadius.circular(12),
                    border: Border.all(color: Colors.black),
                  ),
                  child: IconButton(
                    icon: const Icon(Icons.filter_list),
                    color: Colors.grey[700],
                    onPressed: () {
                      showDialog(
                        context: context,
                        builder: (BuildContext context) {
                          return AlertDialog(
                            title: const Text("Filter Options"),
                            content: Column(
                              mainAxisSize: MainAxisSize.min,
                              children: [
                                ListTile(
                                  title: const Text("Filter 1"),
                                  onTap: () => Navigator.pop(context),
                                ),
                                ListTile(
                                  title: const Text("Filter 2"),
                                  onTap: () => Navigator.pop(context),
                                ),
                                ListTile(
                                  title: const Text("Filter 3"),
                                  onTap: () => Navigator.pop(context),
                                ),
                              ],
                            ),
                          );
                        },
                      );
                    },
                  ),
                ),
              ],
            ),
            const SizedBox(height: 10),
            Expanded(
              child: FutureBuilder<List<dynamic>>(
                future: _sertifikasiFuture,
                builder: (context, snapshot) {
                  if (snapshot.connectionState == ConnectionState.waiting) {
                    return const Center(child: CircularProgressIndicator());
                  } else if (snapshot.hasError) {
                    return Center(child: Text('Error: ${snapshot.error}'));
                  } else if (!snapshot.hasData || snapshot.data!.isEmpty) {
                    return const Center(child: Text('No data available'));
                  } else {
                    final sertifikasis = snapshot.data!;
                    return ListView.builder(
                      itemCount: sertifikasis.length,
                      itemBuilder: (context, index) {
                        final sertifikasi = sertifikasis[index];
                        return Card(
                          color: Colors.white,
                          margin: const EdgeInsets.symmetric(horizontal: 5, vertical: 10),
                          child: ListTile(
                            leading: const Icon(
                              Icons.library_books,
                              size: 35.0,
                              color: Color.fromARGB(255, 55, 94, 151),
                            ),
                            title: Text(
                              sertifikasi['nama_sertifikasi'],
                              style: const TextStyle(
                                fontFamily: 'Poppins',
                                fontSize: 16,
                                color: Color.fromARGB(255, 55, 94, 151),
                                fontWeight: FontWeight.bold,
                              ),
                            ),
                            onTap: () {
                              Navigator.push(
                                context,
                                MaterialPageRoute(
                                  builder: (context) => DetailSertifikasi(
                                    idSertifikasi: sertifikasi['id_sertifikasi'],
                                  ),
                                ),
                              );
                            },
                            trailing: const Icon(
                              Icons.arrow_forward_ios,
                              size: 20.0,
                              color: Color.fromARGB(255, 55, 94, 151),
                            ),
                            contentPadding: const EdgeInsets.all(20),
                          ),
                        );
                      },
                    );
                  }
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}

这是我的 api_service 代码

// lib/services/api_service.dart
import 'package:dio/dio.dart';
import 'package:mobile_smarcerti/app/utils/constant.dart';
import 'package:mobile_smarcerti/app/utils/dio_interceptors.dart';
import 'package:shared_preferences/shared_preferences.dart';

class ApiService {
  late Dio _dio;

  ApiService() {
    _dio = Dio(
      BaseOptions(
        baseUrl: ApiConstants.baseUrl,
        connectTimeout: const Duration(seconds: 5),
        receiveTimeout: const Duration(seconds: 3),
        validateStatus: (status) {
          return status! < 500;
        },
      ),
    );

    _dio.interceptors.add(DioInterceptor());
  }

  Future<Response> get(
    String path, {
    Map<String, dynamic>? queryParameters,
    Options? options,
  }) async {
    try {
      final prefs = await SharedPreferences.getInstance();
      final token = prefs.getString('auth_token');

      final response = await _dio.get(
        path,
        queryParameters: queryParameters,
        options: Options(headers: {
          'Authorization': 'Bearer $token',
          'Accept': 'application/json',
          if (options?.headers != null) ...options!.headers!,
        }),
      );

      return response;
    } on DioException catch (e) {
      throw _handleError(e);
    }
  }

  Future<Response> post(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
  }) async {
    try {
      final prefs = await SharedPreferences.getInstance();
      final token = prefs.getString('auth_token');

      final response = await _dio.post(
        path,
        data: data,
        queryParameters: queryParameters,
        options: Options(
          headers: {
            'Authorization': 'Bearer $token',
            'Accept': 'application/json',
            if (options?.headers != null) ...options!.headers!,
          },
        ),
      );

      return response;
    } on DioException catch (e) {
      throw _handleError(e);
    }
  }

  Exception _handleError(DioException e) {
    if (e.type == DioExceptionType.connectionTimeout) {
      return Exception('Connection timeout');
    }
    if (e.type == DioExceptionType.receiveTimeout) {
      return Exception('Unable to connect to the server');
    }
    if (e.type == DioExceptionType.unknown) {
      return Exception('Something went wrong');
    }

    return Exception(e.message);
  }

  Future<List<dynamic>> fetchSertifikasi() async {
    try {
      final response = await _dio.get('/sertifikasis/');
      if (response.data['success']) {
        return response.data['data'];
      } else {
        throw Exception('Failed to load sertifikasi');
      }
    } catch (e) {
      throw Exception('Failed to load sertifikasi: $e');
    }
  }

我尝试过使用该认证功能创建一个新的 flutter 项目,它工作正常,但当我尝试我的主项目时,它不起作用

我尝试解决这个问题3个小时,结果还是一样。

这是我的虚拟电话中的错误:

Error: Exception: Failed to load sertifikasi: type 'String' is not a subtype of type 'int' of 'index'

这是调试控制台中的错误:

D/EGL_emulation(17071): app_time_stats: avg=426.41ms min=6.15ms max=6485.81ms count=16
W/WindowOnBackDispatcher(17071): OnBackInvokedCallback is not enabled for the application.
W/WindowOnBackDispatcher(17071): Set 'android:enableOnBackInvokedCallback="true"' in the application manifest.
D/EGL_emulation(17071): app_time_stats: avg=28.53ms min=4.21ms max=433.69ms count=29
android flutter dart mobile
1个回答
0
投票

“String”类型不是“index”的“int”类型的子类型当您尝试从键或索引预计为 int 类型的映射或列表中访问值时,通常会遇到这种情况,但是您“重新提供一个字符串(反之亦然)。在您的代码中,问题可能出在 fetchSertifikasi 方法中如何解析 API 响应数据。

可能的问题是:

在 fetchSertifikasi 中,您将返回 response.data['data'],假设它包含动态对象列表(如地图)。但是,在您的主项目中,数据字段可能没有预期的结构,或者某些字段(例如 id_sertifikasi)可能没有正确的数据类型(例如,是 String 而不是 int)。

调试步骤

第 1 步:记录 API 的响应以查看其确切结构并确认数据类型。

第2步:确保数据类型一致 如果 API 将 id_sertifikasi 作为字符串而不是 int 返回,您应该修改处理此数据的方式。

第3步:检查JSON解析 如果您期望 API 提供特定数据类型,请使用模型类来解析和验证 JSON

© www.soinside.com 2019 - 2024. All rights reserved.