You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter集成NASA API:如何将返回字符串转为图片显示?

解决NASA APOD应用展示图片的问题

你的代码目前仅将ApodItem转为字符串输出,要实现图片展示,需利用ApodItem携带的图片URL字段,通过Flutter的Image.network组件加载图片。以下是修改后的完整代码,关键改动已适配图片展示需求:

import 'package:flutter/material.dart';
import 'package:nasa_apis/nasa_apis.dart';
import 'package:tuple/tuple.dart';

class ApodScreen extends StatefulWidget {
  const ApodScreen({super.key, required this.title});

  final String title;

  @override
  State<ApodScreen> createState() => _ApodScreenState();
}

class _ApodScreenState extends State<ApodScreen> {
  static const String _widgetNasaApod = "APOD";

  String _selected = _widgetNasaApod;
  String _apodTestDescription = "The request will appear here.";
  List<ApodItem> _apodTestResults = <ApodItem>[];

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

  void init() async {
    await Nasa.init(
        logReceiver: (String msg, String name) {},
        apodSupport: true,
        apodCacheSupport: true,
        apodDefaultCacheExpiration: const Duration(seconds: 20));
  }

  @override
  Widget build(BuildContext context) {
    List<Widget> widgets = <Widget>[];
    if (_selected == _widgetNasaApod) {
      widgets.add(
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            TextButton(
              onPressed: () async {
                _apodTestResults.clear();
                DateTime date = DateTime.now();
                Tuple2<int, ApodItem?> result = await NasaApod.requestByDate(date);
                _apodTestDescription =
                    "requestByDate()\ndate[${date.toString()}]\nhttp response code: ${result.item1.toString()}";
                if (result.item2 != null) {
                  _apodTestResults.add(result.item2!);
                }
                setState(() {});
              },
              child: const Text("Today"),
            ),
            TextButton(
              onPressed: () async {
                _apodTestResults.clear();
                Tuple2<int, List<ApodItem>?> result = await NasaApod.requestByRandom(5);
                _apodTestDescription =
                    "requestByRandom()\ncount[5]\nhttp response code: ${result.item1.toString()}";
                if (result.item2 != null) {
                  _apodTestResults = result.item2!;
                }
                setState(() {});
              },
              child: const Text("Random"),
            ),
            TextButton(
              onPressed: () async {
                _apodTestResults.clear();
                DateTime startDate = DateTime(2022, 10, 1);
                DateTime endDate = DateTime(2022, 10, 31);
                Tuple2<int, List<MediaType>?> result =
                    (await NasaApod.requestByRange(startDate, endDate)) as Tuple2<int, List<MediaType>?>;
                _apodTestDescription =
                    "requestByOctober()\n$startDate - $endDate\nhttp response code: ${result.item1.toString()}";
                if (result.item2 != null) {
                  _apodTestResults = result.item2!.cast<ApodItem>();
                }
                setState(() {});
              },
              child: const Text("October"),
            ),
          ],
        ),
      );
      widgets.add(Padding(
        padding: const EdgeInsets.all(15),
        child: Text(_apodTestDescription),
      ));
      // 核心修改:替换字符串展示为图片+信息布局
      for (ApodItem apodItem in _apodTestResults) {
        widgets.add(
          Padding(
            padding: const EdgeInsets.all(15),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                // 展示APOD标题
                Text(
                  apodItem.title ?? "无标题",
                  style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                ),
                const SizedBox(height: 8),
                // 根据媒体类型展示内容:图片则加载,视频显示提示
                if (apodItem.mediaType == "image")
                  ClipRRect(
                    borderRadius: BorderRadius.circular(8),
                    child: Image.network(
                      // 优先使用高清图URL,无则用普通图URL
                      apodItem.hdurl ?? apodItem.url ?? "",
                      // 加载中占位
                      loadingBuilder: (context, child, loadingProgress) {
                        if (loadingProgress == null) return child;
                        return Center(
                          child: CircularProgressIndicator(
                            value: loadingProgress.expectedTotalBytes != null
                                ? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes!
                                : null,
                          ),
                        );
                      },
                      // 加载失败提示
                      errorBuilder: (context, error, stackTrace) {
                        return const Center(child: Text("图片加载失败"));
                      },
                      fit: BoxFit.cover,
                      width: double.infinity,
                    ),
                  )
                else
                  const Text("当前内容为视频,暂不支持播放"),
                const SizedBox(height: 8),
                // 展示APOD描述文本
                Text(apodItem.explanation ?? "无描述"),
              ],
            ),
          ),
        );
      }
    }
    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
          onPressed: () {
            Navigator.of(context).pop();
          },
          icon: const BackButtonIcon(),
        ),
        title: Text(widget.title),
      ),
      body: SingleChildScrollView(
        child: Column(
          children: widgets,
        ),
      ),
    );
  }
}

关键修改说明

  1. 替换了原代码中Text(apodItem.toString())的展示逻辑,改为包含标题、图片、描述的垂直布局
  2. 使用Image.network加载图片,添加了加载进度指示器和加载失败提示,提升用户体验
  3. 增加了媒体类型判断,兼容APOD返回的视频内容(若需支持视频可额外集成视频播放组件)
  4. 优先加载高清图URL(hdurl),无高清图时回退到普通图URL(url)

内容的提问来源于stack exchange,提问作者student14142

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 09:15:32