从Future <List <String >>到List <String>以便在常规函数/支架中使用的API调用

时间:2019-10-28 02:19:51

标签: list flutter dart widget

我正在使用TMDb API来获取要显示的图像网址。我可以获取图像网址并将其显示在控制台上。但是,当我尝试创建一个方法并遍历列表中的每个项目时,它始终返回空白(我检查了打印)。

编辑:这两个方法都在同一个类中,并且彼此之间就在字面上。

任何帮助将不胜感激!

List<String> popularMovie = List<String>();

  @override
  void initState() {
    super.initState();
    this.getJsonData();
  }

  //GET POPULAR MOVIE INFO WITH API
  Future<List> getJsonData() async {
    http.Response response = await http.get(
      Uri.encodeFull(popularURL),
      headers: {
        'Accept': 'application/json'
      }
    );


    var popularMovieData = json.decode(response.body);
    var placeholder = popularMovieData['results'];


    //get a list of images only
    for(var item in placeholder) {
      popularMovie.add(item['poster_path']);
   }
    print(popularMovie.length); //20
    print(popularMovie); //prints [imgURL, imageURL, ...]
    return popularMovie;

  } //end of popular movie api function

下面是应该在列表项中循环的方法

//method to iterate through each item and get the image url to display image
  List<Widget> popularMovies() {
    List<Widget> popularMovieList = new List();

  for(var item in popularMovie) { //this is empty
    var popularMovieItem = Padding(
    padding: EdgeInsets.all(10),
    child: Container(
      width: 250,
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(15),
        color: Colors.white,
        boxShadow: [
          BoxShadow(
            color: Colors.grey.withOpacity(0.4),
            spreadRadius: 4,
            blurRadius: 4,
          ),
        ]
      ),
      child: Stack(
        children: <Widget>[
          Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Container(
                height: MediaQuery.of(context).size.height/2 - 20,
                width: MediaQuery.of(context).size.width,
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.all(Radius.circular(15),),
                  image: DecorationImage(
                    image: NetworkImage('https://image.tmdb.org/t/p/w500${item}'),
                    fit: BoxFit.fill,
                  )
                ),
              ),
            ],
          ),
        ],
      ),
    ),
  );
  popularMovieList.add(popularMovieItem);
    }
    return popularMovieList;
  }

最后,我想将页面上的所有电影显示为

children:popularMovies(),

2 个答案:

答案 0 :(得分:1)

由于getJsonData是一个异步函数,因此您需要使用FutureBuider,否则您需要调用popularMovie

而不是返回setState
FutureBuilder<String>(
  future: getJsonData,
  builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
    switch (snapshot.connectionState) {
      case ConnectionState.none:
        return Text('Press button to start.');
      case ConnectionState.active:
      case ConnectionState.waiting:
        return Text('Awaiting result...');
      case ConnectionState.done:
        if (snapshot.hasError)
          return Text('Error: ${snapshot.error}');
        return Text('Result: ${snapshot.data}');
    }
    return null; // unreachable
  },
)

答案 1 :(得分:0)

我终于明白了!使用setState超级容易,因此如果有人需要解决方案来转换 Future<List<String>> to List<String>,然后将其用作支架中的普通列表,这就是我所做的:

首先,声明您的列表变量:

List<String> popularMovie = List<String>(); //declare a list inside the class

然后进行http调用,并将“所需项列表”分配给先前声明的列表变量“ inside setState”

@override
  void initState() {
    super.initState();
    this.getJsonData();
  }

  //GET POPULAR MOVIE INFO WITH API
  Future<List<String>> getJsonData() async {
    http.Response response = await http.get(
      Uri.encodeFull(popularURL),
      headers: {
        'Accept': 'application/json'
      }
    );

    setState(() { //only get the first 10 movie images
      var popularMovieData = json.decode(response.body);
      for (int i = 0; i < 10; i++) {
        popularMovie.add(popularMovieData['results'][i]['poster_path']);      
      }
      print(popularMovie);
    });

  } //end of popular movie api function

然后,我创建了一个方法来创建一个小部件以显示每个图像,该方法与我在原始帖子中创建的方法相同,就像这样:

List<Widget> popularMovies() {

最后,我想以这种方式显示它(您可以执行此操作):

Padding(
            padding: EdgeInsets.only(left: 10, top: 10, bottom: 10),
            child: Container(
              height: MediaQuery.of(context).size.height/2,
              child: ListView(
                scrollDirection: Axis.horizontal,
                children: popularMovies(), //display all images in a horizontal row
              ),
            ),
          ),

您完成了! :)