简体   繁体   中英

type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Session' in type cast

new to Dart / Flutter here. I created a gridview and upon tapping an item in the grid, I'd like to pass my JSON data to the next page. However, I'm getting an error that I believe has something to do with not typecasting properly. I'd like the next page to display a title, description and image (the same data that gets displayed in a gridview) but I get an error that says type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'Session' in type cast .

Here's my code:

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)
          ),
        ]
      )
    );
  }
}

I'm kinda stuck and any help would be appreciated!

Because you are using fetched json directly. First of all, convert your body into Map :

Map.from(jsonDecode(body));

body is that _InternalLinkedHashMap<String, dynamic> data in your case.

Then add your fromJson factory into your class:

class Session{
...
  factory Session.fromJson(Map<String, Object> json) {
    return Session(json['title'], json['description'], json['image']);
  }
...

And by using decoded Map from your request, put it that factory, you'll get objects.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM