forked from firka/firka
login_screen: cache images
This commit is contained in:
86
firka/lib/helpers/cache_memory_image_provider.dart
Normal file
86
firka/lib/helpers/cache_memory_image_provider.dart
Normal file
@@ -0,0 +1,86 @@
|
||||
import 'dart:ui';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
// Taken from https://gist.github.com/darmawan01/9be266df44594ea59f07032e325ffa3b
|
||||
// and adapted to use assets
|
||||
|
||||
final _globalImageCache = <String, Uint8List>{};
|
||||
|
||||
Future<void> precacheAsset(AssetBundle bundle, String asset) async {
|
||||
if (!_globalImageCache.containsKey(asset)) {
|
||||
final data = await bundle.load(asset);
|
||||
_globalImageCache[asset] = data.buffer.asUint8List();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> precacheAssets(AssetBundle bundle, List<String> assets) async {
|
||||
for (final asset in assets) {
|
||||
await precacheAsset(bundle, asset);
|
||||
}
|
||||
}
|
||||
|
||||
Future<Uint8List> _cacheLoad(AssetBundle bundle, String asset) async {
|
||||
if (!_globalImageCache.containsKey(asset)) {
|
||||
final data = await bundle.load(asset);
|
||||
_globalImageCache[asset] = data.buffer.asUint8List();
|
||||
}
|
||||
|
||||
return Future.value(_globalImageCache[asset]!);
|
||||
}
|
||||
|
||||
class CacheMemoryImageProvider extends ImageProvider<CacheMemoryImageProvider> {
|
||||
final AssetBundle bundle;
|
||||
final String path;
|
||||
Uint8List? _img;
|
||||
|
||||
CacheMemoryImageProvider(this.bundle, this.path);
|
||||
|
||||
@override
|
||||
ImageStreamCompleter loadImage(
|
||||
CacheMemoryImageProvider key, ImageDecoderCallback decode) {
|
||||
return MultiFrameImageStreamCompleter(
|
||||
codec: _loadAsync(decode),
|
||||
scale: 1.0,
|
||||
debugLabel: path,
|
||||
informationCollector: () sync* {
|
||||
yield ErrorDescription('Tag: $path');
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<Codec> _loadAsync(ImageDecoderCallback decode) async {
|
||||
_img ??= await _cacheLoad(bundle, path);
|
||||
|
||||
// the DefaultCacheManager() encapsulation, it get cache from local storage.
|
||||
final Uint8List bytes = _img!;
|
||||
|
||||
if (bytes.lengthInBytes == 0) {
|
||||
// The file may become available later.
|
||||
PaintingBinding.instance.imageCache.evict(this);
|
||||
throw StateError('$path is empty and cannot be loaded as an image.');
|
||||
}
|
||||
final buffer = await ImmutableBuffer.fromUint8List(bytes);
|
||||
|
||||
return await decode(buffer);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<CacheMemoryImageProvider> obtainKey(ImageConfiguration configuration) {
|
||||
return SynchronousFuture<CacheMemoryImageProvider>(this);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType) return false;
|
||||
bool res = other is CacheMemoryImageProvider && other.path == path;
|
||||
return res;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => path.hashCode;
|
||||
|
||||
@override
|
||||
String toString() =>
|
||||
'${objectRuntimeType(this, 'CacheImageProvider')}("$path")';
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import 'package:carousel_slider/carousel_slider.dart';
|
||||
import 'package:firka/helpers/api/client/kreta_client.dart';
|
||||
import 'package:firka/helpers/api/consts.dart';
|
||||
import 'package:firka/helpers/db/models/token_model.dart';
|
||||
import 'package:firka/helpers/firka_bundle.dart';
|
||||
import 'package:firka/main.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -11,6 +12,7 @@ import 'package:flutter/services.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
|
||||
import '../../../../helpers/api/token_grant.dart';
|
||||
import '../../../../helpers/cache_memory_image_provider.dart';
|
||||
import '../../../model/style.dart';
|
||||
import '../home/home_screen.dart';
|
||||
|
||||
@@ -26,6 +28,8 @@ class LoginScreen extends StatefulWidget {
|
||||
class _LoginScreenState extends State<LoginScreen> {
|
||||
late WebViewController _webViewController;
|
||||
|
||||
bool _preloadDone = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@@ -87,6 +91,25 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
statusBarColor: Colors.transparent,
|
||||
systemNavigationBarColor: Color(0xFFFAFFF0),
|
||||
));
|
||||
|
||||
() async {
|
||||
final firkaBundle = FirkaBundle();
|
||||
|
||||
await precacheAssets(firkaBundle, [
|
||||
"assets/images/carousel/slide1.png",
|
||||
"assets/images/carousel/slide1_background.gif",
|
||||
"assets/images/carousel/slide2.png",
|
||||
"assets/images/carousel/slide2_background.gif",
|
||||
"assets/images/carousel/slide3.png",
|
||||
"assets/images/carousel/slide3_foreground.gif",
|
||||
"assets/images/carousel/slide4.png",
|
||||
"assets/images/carousel/slide4_background.gif"
|
||||
]);
|
||||
|
||||
setState(() {
|
||||
_preloadDone = true;
|
||||
});
|
||||
}();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -96,6 +119,12 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (!_preloadDone) {
|
||||
return MaterialApp(
|
||||
home: SizedBox(),
|
||||
);
|
||||
}
|
||||
|
||||
final paddingWidthHorizontal = MediaQuery.of(context).size.width -
|
||||
MediaQuery.of(context).size.width * 0.95;
|
||||
List<Map<String, Object>> slides = [
|
||||
@@ -167,8 +196,9 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
height: 30,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
decoration: ShapeDecoration(
|
||||
image: const DecorationImage(
|
||||
image: AssetImage(
|
||||
image: DecorationImage(
|
||||
image: CacheMemoryImageProvider(
|
||||
DefaultAssetBundle.of(context),
|
||||
'assets/images/logos/colored_logo.png'),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
@@ -240,8 +270,11 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
scale: slides[index]['scale']
|
||||
as double,
|
||||
child: Image(
|
||||
image: AssetImage(slides[index]
|
||||
['background']! as String),
|
||||
image: CacheMemoryImageProvider(
|
||||
DefaultAssetBundle.of(
|
||||
context),
|
||||
slides[index]['background']!
|
||||
as String),
|
||||
fit: BoxFit.contain,
|
||||
width: double.infinity,
|
||||
)),
|
||||
@@ -257,7 +290,8 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
child: SizedBox(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Image(
|
||||
image: AssetImage(
|
||||
image: CacheMemoryImageProvider(
|
||||
DefaultAssetBundle.of(context),
|
||||
slides[index]['picture']! as String),
|
||||
fit: BoxFit.cover,
|
||||
width: double.infinity,
|
||||
@@ -285,8 +319,11 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
scale: slides[index]['scale']
|
||||
as double,
|
||||
child: Image(
|
||||
image: AssetImage(slides[index]
|
||||
['foreground']! as String),
|
||||
image: CacheMemoryImageProvider(
|
||||
DefaultAssetBundle.of(
|
||||
context),
|
||||
slides[index]['foreground']!
|
||||
as String),
|
||||
fit: BoxFit.cover,
|
||||
width: MediaQuery.of(context)
|
||||
.size
|
||||
|
||||
Reference in New Issue
Block a user