android - 类型 '_InternalLinkedHashMap<String, dynamic>'不是类型转换中类型 'Session'的子类型

标签 android oop flutter dart mobile

Dart / Flutter的新功能。我创建了一个gridview,然后在网格中点击一个项目后,我想将JSON数据传递到下一页。但是,我收到一个错误,我认为这与无法正确进行类型转换有关。我希望下一页显示标题,描述和图像(在gridview中显示的数据相同),但是出现错误消息type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Session' in type cast

这是我的代码:

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

/*
 Build a custom media widget that takes all the attributes from its JSON index.
 1. FutureBuilder to build the UI based on data that we wait to receive (Future)
 2. For each item in JSON, return a styled grid item containing the metadata
 3. Text should be part of the component as well
 4. Pass metadata in as arguments to the session information page/widget
 5. Use an onTap() + Navigator.push() to select the audio file
 6. Also use this https://flutter.dev/docs/cookbook/navigation/hero-animations
*/

class ExplorerGrid extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        margin: EdgeInsets.only(left: 8.0, right: 8.0),
        child: FutureBuilder(
            // an asset :bundle is just the resources used by a given application
            future:
                DefaultAssetBundle.of(context).loadString('audio/media.json'),
            builder: (context, snapshot) {

              // Loading indicator
              if (!snapshot.hasData) {
                return CircularProgressIndicator();
              }

              if (snapshot.hasError) {
                return Text(snapshot.error); // or whatever
              }

              var mediaData = json.decode(snapshot.data.toString());
              List<Session> mediaDataSession = (mediaData as List<dynamic>).cast<Session>();

              return GridView.builder(
                  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                    crossAxisCount: 2,
                    crossAxisSpacing: 10,
                    childAspectRatio: 0.83,
                  ),
                  itemCount: mediaData.length,
                  itemBuilder: (BuildContext context, int index) {
                    // Column should consist of Image, title and description / metadata
                    return Container(
                      margin: EdgeInsets.only(top: 12.0),
                      child: InkWell(
                        highlightColor: Colors.green[100],
                        borderRadius: BorderRadius.circular(4.0),
                        onTap: () => {
                          // Route and build the metadata page based on the widget clicked
                          Navigator.push(
                            context,
                            MaterialPageRoute(
                              // session: needs to receive a List with the type of Session e.g. List<Session>
                              builder: (context) => SessionMetadata(session: mediaDataSession[index])
                            )
                          )
                        },
                        child: Column(
                          children: [
                            FittedBox(
                              child: ClipRRect(
                                borderRadius: BorderRadius.circular(30.0),
                                child: Image(
                                  image: AssetImage(mediaData[index]['image']),
                                ),
                              ),
                              fit: BoxFit.fill,
                            ),

                            // Session Title Row
                            Row(
                              children: <Widget>[
                                Expanded(
                                  child: Padding(
                                    padding: EdgeInsets.only(top: 8.0),
                                    child: Text(
                                      mediaData[index]['name'],
                                      style: TextStyle(
                                          fontWeight: FontWeight.bold,
                                          fontFamily: 'Bryant',
                                          fontSize: 17.0),
                                    ),
                                  ),
                                ),
                              ],
                            ),

                            // Description Row
                            Flexible(
                              child: Row(
                                children: [
                                  Flexible(
                                    child: Padding(
                                      padding: const EdgeInsets.only(left: 0.0),
                                      child: Text(
                                        mediaData[index]['description'],
                                        style: TextStyle(
                                          fontWeight: FontWeight.normal,
                                          fontFamily: 'Bryant',
                                          fontSize: 14.0,
                                        ),
                                        overflow: TextOverflow.ellipsis,
                                        maxLines: 3,
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ],
                        ),
                      ),
                    );
                  });
            }),
      ),
    );
  }
}

// A way to represent a session and a session metadata page below
class Session {
  // Variables for storing metadata
  final String title;
  final String description;
  final String image;

  Session(this.title, this.description, this.image);
}

// Create a page that we pass session metadata to
class SessionMetadata extends StatelessWidget {
  final Session session;

  // Constructor to require this information
  SessionMetadata({ Key key, @required this.session}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(session.title),
      ),
      body: Column(
        children: [
          Image(
              image: AssetImage(session.image)
          ),
          Padding(
              padding: EdgeInsets.all(8.0),
              child: Text(session.description)
          ),
        ]
      )
    );
  }
}

我有点卡住,任何帮助将不胜感激!

最佳答案

因为您直接使用提取的json。首先,将body转换为Map:

Map.from(jsonDecode(body));

主体是您的情况下的_InternalLinkedHashMap<String, dynamic>数据。

然后将fromJson工厂添加到您的类中:
class Session{
...
  factory Session.fromJson(Map<String, Object> json) {
    return Session(json['title'], json['description'], json['image']);
  }
...

然后,通过使用请求中解码的Map将该代码放到工厂中,您将获得对象。

关于android - 类型 '_InternalLinkedHashMap<String, dynamic>'不是类型转换中类型 'Session'的子类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61767689/

相关文章:

python - 在 `self` 语句中使用 `with` 作为上下文

firebase - 如何使用 Flutter 获取 Firebase 存储目录中的所有文件

node.js - 如何在 Flutter android 应用程序中发送推送通知?

java - 为什么我的 View 数组返回 null?

oop - 为什么类的私有(private)部分被视为接口(interface)?

php - Android C2DM 缺少注册错误?

c++ - 在模板类中设置动态构造函数参数的方法

user-interface - Flutter 中的水平按钮组

android - 其他选项菜单项在展开的搜索 View 折叠后不显示

android - 九补丁内容区域不起作用