gpt4 book ai didi

android - 用MySQL flutter 无限 ScrollView

转载 作者:行者123 更新时间:2023-11-29 11:32:40 25 4
gpt4 key购买 nike

最近,我从事类似项目的画廊工作,该项目显示了数据库中的大量图像。我使用MySQL是因为我拥有专用服务器,并且由于价格原因,使用Firestore可能不是一个好主意。我希望它有一个无限滚动 View ,每次加载10张图像,但是当前它同时加载所有图像,这使应用程序感觉真的很慢。

这是我的lib / main.dart

import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:http/http.dart' as http;
//local import, you can ignore it
import './nav.dart';
import './detail.dart';
import './placeholder.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
@override
_MyApp createState() => new _MyApp();
}

class _MyApp extends State<MyApp> {
Future<List> getData() async {
final resp = await http.get("http://192.168.43.68/API/readImage.php");
return json.decode(resp.body);
}

@override
Widget build(BuildContext context) {
// TODO: implement build
return new MaterialApp(
theme: new ThemeData.dark(),
home: Scaffold(
appBar: new AppBar(
title: new Text("Title"),
),
drawer: Nav(),
body: new FutureBuilder(
future: getData(),
builder: (context, snapshot) {
if (snapshot.hasError) {
print(snapshot.error);
}

return snapshot.hasData
? new ItemList(
list: snapshot.data,
)
: new Center(child: new CircularProgressIndicator());
},),),);}}


//Item builder to display each image
class ItemList extends StatelessWidget {
final List list;
ItemList({this.list});

@override
Widget build(BuildContext context) {
// TODO: implement build
return new Padding(
padding: const EdgeInsets.all(0.0),
child: new StaggeredGridView.countBuilder(
crossAxisCount: 4,
itemCount: list.length,
itemBuilder: (BuildContext context, int index) => new Container(
child: new GestureDetector(
onTap: () => Navigator.of(context).push(new MaterialPageRoute(
builder: (BuildContext context) => new Detail(
list: list,
index: index,
))),
child: Card(
child: new Column(
children: <Widget>[
new Stack(
children: <Widget>[
FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image: list[index]['url'],
),],),

new Padding(
padding: EdgeInsets.all(4.0),
child: new Column(
children: <Widget>[
new Text(list[index]['name'],
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white70,
))],),)],),))),
staggeredTileBuilder: (index) => new StaggeredTile.fit(2),
),);}}

这是我的readImage.php(我仍然不知道该怎么办)
<?php
include 'dbcon.php';
$sth = "SELECT * FROM pict INNER JOIN user ON pict.uid=user.uid LIMIT 10";

$result = $conn->query($sth);
$outp = array();
$outp = $result->fetch_all(MYSQLI_ASSOC);

echo json_encode($outp);

enter code here

因此,任何回应都将不胜感激。

最佳答案

我相信您遇到的主要问题是您正在使用StaggeredTile.fit()。

一些背景信息:在抖动中,图像大小不是立即确定的,而是一旦图像实际加载就确定了。这对于少量的图像很好,但是当数量较大(可能无限)时,会引起问题。

这样做的原因是,在第一次构建列表时,它会布局足够的子级以适合屏幕(+ cacheExtent,这可能不适用于StaggeredGridView,但适用于大多数抖动列表)。考虑一下列表中的每个项目将如何布局-GestureDetector,Card,Column和Stack为其子代分配的所有委托(delegate)大小。因此,尺寸取决于图像。占位符并不能真正确定高度,因此您可以想到高度为零或一的图像。

这意味着在您的页面中,随着越来越多的项目添加到屏幕上,它不断尝试加载越来越多的图像-垂直像素数或基本上是无限像素,具体取决于占位符高度的处理方式。

有一个简单的解决方案,但是它可能对您没有吸引力-而不是使用StaggeredTile.fit(),而是使用固定的高度,然后使图像适合该高度。

不幸的是,如果您希望每个图像都具有不同的高度,它将变得更加复杂。解决此问题的一种方法(因为您可以控制数据库)是将纵横比以及每个图像的路径存储在数据库中。这样,您可以使用AspectRatio小部件包装FaceInImage,因此可以立即确定高度。

当然,这仅在您的项目列表不是真正无限的情况下才有效,但是由于它在数据库中,所以我认为假定= D是相当安全的。您可以在PHP中使用the getimagesize function来计算每个图像的长宽比,这样做就可以遍历整个数据库,然后从现在开始,每当插入新图像时,都必须计算长宽比。

另一个解决方案是从您指定自己的固定高度开始,然后在加载图像后更改高度。但是,我不知道StaggeredGridView将如何处理-我见过的大多数列表/网格类都希望他们的 child 保持相同的大小。在这种情况下,您可能必须查看CustomScrollView并编写自己的条,这超出了此问题的范围。

编辑:OP澄清说,显然MySQL部分是他们要问的,而不是为什么它很慢。我仍然认为图像是为什么它慢而不是对URL的请求的原因,但是我可能是错的。尚未指定是要加载10、50、100还是1000张图像。

如果没有更多有关如何设置数据库的知识,就很难给出明确的答案。但是,我将快速概述一下设置服务器的可能方法。

我不会为您的服务器编写实际的代码,因为这超出了关于抖动的SO问题的范围。如果您不知道该如何解决,我建议您先找到一门有关设置服务器的类(class)或教程,然后再问一个问题而不是用flutter标记,而是用PHP / MySQL等标记,因为实际上您对的要求是什么,是关于您遇到的特定问题,而不是一般的“我无法帮助您”的问题,因为这样无法得到解答。

假设以下内容:

  • 您已经建立了一个数据库,可以查询URL,描述等列表
  • 此数据库应返回大量值(例如,超过200个或更多)

  • 在服务器端,您将必须设置一个端点来响应请求并返回数据部分。如果希望使用JSON,我希望没有参数的端点返回类似以下的内容:
    {
    num: 30,
    images: [
    { title: ..., url: ..., .... },
    ...
    ],
    more: true
    }

    并且该列表必须按某些参数进行排序-标题,日期,ID等。您还可以选择一个 totalItems,该返回值作为结果的一部分告诉客户端有多少个图像。您也可以选择接受要退回的商品数量。

    对于后续请求,您可以接受参数 numoffset。偏移量应该是描述返回的最后结果的一种方式,以便查询知道从何处开始-如果按ID排序,则可能是那个,或者按日期,可能是日期。 num将是要返回的最大结果数。

    如果您不将totalItems作为响应的一部分返回,则可以选择有一个不同的请求,该请求仅向您提供最大数量的项目,因为这可能会使您的生活变得更轻松。如果您不想执行任何一项操作,请查看 the link someone posted in a comment,它描述了如何编写无限加载列表。

    注意,这只会返回图像的URL,而不是图像本身。

    接下来,您将需要建立某种系统来缓存Flutter代码。这可能会变得有些复杂,因为在页面滚动时,您不仅必须获取图像,而且还必须获取图像的描述。

    我将如何做如下:
  • 创建一个分页管理器来处理加载项目描述
  • 分页管理器可以请求商品,即从0开始,num 30
  • 分页管理器启动此请求并跟踪它
  • 每个单独的列表项都向分页管理器
  • 请求其数据
  • 每个列表项都有一个FutureBuilder,它会在加载数据时显示某些内容,而在加载数据时显示其他内容。
  • 管理器知道是否已针对该项目启动请求,如果不是,则对该项目+及其周围的项目发出请求(这样就不会立即发送一堆单独的请求)
  • 该列表项返回到将来,将仅返回其数据,如果已加载数据,该列表项立即完成,或者等待直到从服务器返回数据
  • 如果您有很多图像,在某个时候,您可能想在缓存管理器中取消初始化数据-您可以通过跟踪当前正在请求哪些图像并删除所有<100降低或> 100或更高的图像来完成此操作这样的事情。


  • 还有另一种方法可以执行此操作,但对于您的数据库可能并不是特别理想(取决于它的设置方式)。您无需在客户端进行缓存,只需向服务器发送每个图像的请求(即GET user / images / 1,user / images / 2等)。然后,您的服务器将在内部确定从何处加载该图像,并将以标题等作为标题直接返回。

    这样做的问题是,幼稚的方法是对每个传入的请求都执行数据库请求。这会起作用,但会导致对数据库的大量请求。根据您的数据库设置,可能还可以,但是最终很可能会导致问题。取而代之的是,您可以在服务器上批量处理请求(即,如果请求为0,也获取并缓存0-30),然后只需对缓存的数据进行处理即可。我将其留给您实现,因为它超出了此问题的范围。

    关于android - 用MySQL flutter 无限 ScrollView ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51988852/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com