admin管理员组

文章数量:1023803

I have a page with a ListView, each tile contains an image and text. The tiles are generated from a list of objects. Each object has properties text and imageId. imageId is used to retrieve the image from the "images" table in the local database. The "images" table has columns id (TEXT) and picture (BLOB). I am using SQLite with sqflite (mobile) and sqflite_common_ffi (desktop).

List<Request> _requests = [];
List<ImagesItem> _images = [];
bool _isLoading = true;

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

void loadRequests() async {
  try {
    var requests = await RequestsRepository().getAllRequests();
    requests = requests.take(1).toList(); // take(1) for testing purposes
    var alreadyStoredImages = _images.map((image) => image.id).toSet();
    var images = await ImageRepository().getImagesByIds(
      requests
          .map((request) => request.imageId)
          .where((imageId) => !alreadyStoredImages.contains(imageId))
          .toList(),
    );

    setState(() {
      _images = images;
      _requests = requests;
    });
  } catch (error) {
    // Handle error
  } finally {
    setState(() {
      _isLoading = false;
    });
  }
}

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: _isLoading
        ? const Center(child: CircularProgressIndicator())
        : ListView.builder(
            itemCount: _requests.length,
            itemBuilder: (context, index) {
              final request = _requests[index];
              final image = _images.firstWhere(
                (img) => img.id == request.imageId,
              );
              return ListTile(
                leading: Image.memory(
                  image.picture,
                  width: 50,
                  height: 50,
                ),
              );
            },
          ),
  );
}

The text appears instantly but the images take about 2 seconds to load. Is it normal for images to take this long to load from a local database? I could show a loader before showing the ListView but I don't know how to let the Image Widget load the image and after that show everything.

In another attempt with PrecacheImage the images are MemoryImage instead of Uint8List. The Image widget uses MemoryImage instead of Image.memory(). The page loads almost instantly. The code changed with precacheImage:

class _RequestWithImagePreCache {
  final String id;
  final MemoryImage image;

  _RequestWithImagePreCache(this.id, this.image);
}
List<_RequestWithImagePreCache> _images = [];

void loadRequests() async {
    try {
      var requests = await RequestsRepository().getAllRequests();
    requests = requests.take(1).toList(); // take(1) for testing purposes
      var alreadyStoredImages = _images.map((image) => image.id).toSet();
      var images = await ImageRepository().getImagesByIds(
        requests
            .map((request) => request.imageId)
            .where((imageId) => !alreadyStoredImages.contains(imageId))
            .toList(),
      );

      List<_RequestWithImagePreCache> imagesCached = [];
      await Future.wait(images.map((image) async {
        final memoryImage = MemoryImage(image.picture);
        await precacheImage(memoryImage, context);
        imagesCached.add(_RequestWithImagePreCache(image.id, memoryImage));
      }));

      setState(() {
        _images = imagesCached;
        _requests = requests;
      });
    } catch (error) {
      // Handle any errors during data fetching
    } finally {
      setState(() {
        _isLoading = false;
      });
    }
  }

The use of precacheImage is not clear to me as all guides use it in the context of images retrieved from the web, or use the package cached_network_image which I believe uses precacheImage or something similar. Is there a behavior to follow and why does the second case load faster even if I have to push images to cache instead of directly using them after retrieving from database?

I have a page with a ListView, each tile contains an image and text. The tiles are generated from a list of objects. Each object has properties text and imageId. imageId is used to retrieve the image from the "images" table in the local database. The "images" table has columns id (TEXT) and picture (BLOB). I am using SQLite with sqflite (mobile) and sqflite_common_ffi (desktop).

List<Request> _requests = [];
List<ImagesItem> _images = [];
bool _isLoading = true;

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

void loadRequests() async {
  try {
    var requests = await RequestsRepository().getAllRequests();
    requests = requests.take(1).toList(); // take(1) for testing purposes
    var alreadyStoredImages = _images.map((image) => image.id).toSet();
    var images = await ImageRepository().getImagesByIds(
      requests
          .map((request) => request.imageId)
          .where((imageId) => !alreadyStoredImages.contains(imageId))
          .toList(),
    );

    setState(() {
      _images = images;
      _requests = requests;
    });
  } catch (error) {
    // Handle error
  } finally {
    setState(() {
      _isLoading = false;
    });
  }
}

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: _isLoading
        ? const Center(child: CircularProgressIndicator())
        : ListView.builder(
            itemCount: _requests.length,
            itemBuilder: (context, index) {
              final request = _requests[index];
              final image = _images.firstWhere(
                (img) => img.id == request.imageId,
              );
              return ListTile(
                leading: Image.memory(
                  image.picture,
                  width: 50,
                  height: 50,
                ),
              );
            },
          ),
  );
}

The text appears instantly but the images take about 2 seconds to load. Is it normal for images to take this long to load from a local database? I could show a loader before showing the ListView but I don't know how to let the Image Widget load the image and after that show everything.

In another attempt with PrecacheImage the images are MemoryImage instead of Uint8List. The Image widget uses MemoryImage instead of Image.memory(). The page loads almost instantly. The code changed with precacheImage:

class _RequestWithImagePreCache {
  final String id;
  final MemoryImage image;

  _RequestWithImagePreCache(this.id, this.image);
}
List<_RequestWithImagePreCache> _images = [];

void loadRequests() async {
    try {
      var requests = await RequestsRepository().getAllRequests();
    requests = requests.take(1).toList(); // take(1) for testing purposes
      var alreadyStoredImages = _images.map((image) => image.id).toSet();
      var images = await ImageRepository().getImagesByIds(
        requests
            .map((request) => request.imageId)
            .where((imageId) => !alreadyStoredImages.contains(imageId))
            .toList(),
      );

      List<_RequestWithImagePreCache> imagesCached = [];
      await Future.wait(images.map((image) async {
        final memoryImage = MemoryImage(image.picture);
        await precacheImage(memoryImage, context);
        imagesCached.add(_RequestWithImagePreCache(image.id, memoryImage));
      }));

      setState(() {
        _images = imagesCached;
        _requests = requests;
      });
    } catch (error) {
      // Handle any errors during data fetching
    } finally {
      setState(() {
        _isLoading = false;
      });
    }
  }

The use of precacheImage is not clear to me as all guides use it in the context of images retrieved from the web, or use the package cached_network_image which I believe uses precacheImage or something similar. Is there a behavior to follow and why does the second case load faster even if I have to push images to cache instead of directly using them after retrieving from database?

Share Improve this question edited Nov 19, 2024 at 23:01 user4157124 2,99614 gold badges31 silver badges46 bronze badges asked Nov 19, 2024 at 8:25 Bug DepartmentBug Department 112 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

as I read precacheImage concept is like Cache image in CacheManager in theory it should slow on load image first time and store it in cache when reused the same image it will used cache instead of make a new one instant

I have a page with a ListView, each tile contains an image and text. The tiles are generated from a list of objects. Each object has properties text and imageId. imageId is used to retrieve the image from the "images" table in the local database. The "images" table has columns id (TEXT) and picture (BLOB). I am using SQLite with sqflite (mobile) and sqflite_common_ffi (desktop).

List<Request> _requests = [];
List<ImagesItem> _images = [];
bool _isLoading = true;

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

void loadRequests() async {
  try {
    var requests = await RequestsRepository().getAllRequests();
    requests = requests.take(1).toList(); // take(1) for testing purposes
    var alreadyStoredImages = _images.map((image) => image.id).toSet();
    var images = await ImageRepository().getImagesByIds(
      requests
          .map((request) => request.imageId)
          .where((imageId) => !alreadyStoredImages.contains(imageId))
          .toList(),
    );

    setState(() {
      _images = images;
      _requests = requests;
    });
  } catch (error) {
    // Handle error
  } finally {
    setState(() {
      _isLoading = false;
    });
  }
}

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: _isLoading
        ? const Center(child: CircularProgressIndicator())
        : ListView.builder(
            itemCount: _requests.length,
            itemBuilder: (context, index) {
              final request = _requests[index];
              final image = _images.firstWhere(
                (img) => img.id == request.imageId,
              );
              return ListTile(
                leading: Image.memory(
                  image.picture,
                  width: 50,
                  height: 50,
                ),
              );
            },
          ),
  );
}

The text appears instantly but the images take about 2 seconds to load. Is it normal for images to take this long to load from a local database? I could show a loader before showing the ListView but I don't know how to let the Image Widget load the image and after that show everything.

In another attempt with PrecacheImage the images are MemoryImage instead of Uint8List. The Image widget uses MemoryImage instead of Image.memory(). The page loads almost instantly. The code changed with precacheImage:

class _RequestWithImagePreCache {
  final String id;
  final MemoryImage image;

  _RequestWithImagePreCache(this.id, this.image);
}
List<_RequestWithImagePreCache> _images = [];

void loadRequests() async {
    try {
      var requests = await RequestsRepository().getAllRequests();
    requests = requests.take(1).toList(); // take(1) for testing purposes
      var alreadyStoredImages = _images.map((image) => image.id).toSet();
      var images = await ImageRepository().getImagesByIds(
        requests
            .map((request) => request.imageId)
            .where((imageId) => !alreadyStoredImages.contains(imageId))
            .toList(),
      );

      List<_RequestWithImagePreCache> imagesCached = [];
      await Future.wait(images.map((image) async {
        final memoryImage = MemoryImage(image.picture);
        await precacheImage(memoryImage, context);
        imagesCached.add(_RequestWithImagePreCache(image.id, memoryImage));
      }));

      setState(() {
        _images = imagesCached;
        _requests = requests;
      });
    } catch (error) {
      // Handle any errors during data fetching
    } finally {
      setState(() {
        _isLoading = false;
      });
    }
  }

The use of precacheImage is not clear to me as all guides use it in the context of images retrieved from the web, or use the package cached_network_image which I believe uses precacheImage or something similar. Is there a behavior to follow and why does the second case load faster even if I have to push images to cache instead of directly using them after retrieving from database?

I have a page with a ListView, each tile contains an image and text. The tiles are generated from a list of objects. Each object has properties text and imageId. imageId is used to retrieve the image from the "images" table in the local database. The "images" table has columns id (TEXT) and picture (BLOB). I am using SQLite with sqflite (mobile) and sqflite_common_ffi (desktop).

List<Request> _requests = [];
List<ImagesItem> _images = [];
bool _isLoading = true;

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

void loadRequests() async {
  try {
    var requests = await RequestsRepository().getAllRequests();
    requests = requests.take(1).toList(); // take(1) for testing purposes
    var alreadyStoredImages = _images.map((image) => image.id).toSet();
    var images = await ImageRepository().getImagesByIds(
      requests
          .map((request) => request.imageId)
          .where((imageId) => !alreadyStoredImages.contains(imageId))
          .toList(),
    );

    setState(() {
      _images = images;
      _requests = requests;
    });
  } catch (error) {
    // Handle error
  } finally {
    setState(() {
      _isLoading = false;
    });
  }
}

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: _isLoading
        ? const Center(child: CircularProgressIndicator())
        : ListView.builder(
            itemCount: _requests.length,
            itemBuilder: (context, index) {
              final request = _requests[index];
              final image = _images.firstWhere(
                (img) => img.id == request.imageId,
              );
              return ListTile(
                leading: Image.memory(
                  image.picture,
                  width: 50,
                  height: 50,
                ),
              );
            },
          ),
  );
}

The text appears instantly but the images take about 2 seconds to load. Is it normal for images to take this long to load from a local database? I could show a loader before showing the ListView but I don't know how to let the Image Widget load the image and after that show everything.

In another attempt with PrecacheImage the images are MemoryImage instead of Uint8List. The Image widget uses MemoryImage instead of Image.memory(). The page loads almost instantly. The code changed with precacheImage:

class _RequestWithImagePreCache {
  final String id;
  final MemoryImage image;

  _RequestWithImagePreCache(this.id, this.image);
}
List<_RequestWithImagePreCache> _images = [];

void loadRequests() async {
    try {
      var requests = await RequestsRepository().getAllRequests();
    requests = requests.take(1).toList(); // take(1) for testing purposes
      var alreadyStoredImages = _images.map((image) => image.id).toSet();
      var images = await ImageRepository().getImagesByIds(
        requests
            .map((request) => request.imageId)
            .where((imageId) => !alreadyStoredImages.contains(imageId))
            .toList(),
      );

      List<_RequestWithImagePreCache> imagesCached = [];
      await Future.wait(images.map((image) async {
        final memoryImage = MemoryImage(image.picture);
        await precacheImage(memoryImage, context);
        imagesCached.add(_RequestWithImagePreCache(image.id, memoryImage));
      }));

      setState(() {
        _images = imagesCached;
        _requests = requests;
      });
    } catch (error) {
      // Handle any errors during data fetching
    } finally {
      setState(() {
        _isLoading = false;
      });
    }
  }

The use of precacheImage is not clear to me as all guides use it in the context of images retrieved from the web, or use the package cached_network_image which I believe uses precacheImage or something similar. Is there a behavior to follow and why does the second case load faster even if I have to push images to cache instead of directly using them after retrieving from database?

Share Improve this question edited Nov 19, 2024 at 23:01 user4157124 2,99614 gold badges31 silver badges46 bronze badges asked Nov 19, 2024 at 8:25 Bug DepartmentBug Department 112 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

as I read precacheImage concept is like Cache image in CacheManager in theory it should slow on load image first time and store it in cache when reused the same image it will used cache instead of make a new one instant

本文标签: