Android-Universal-Image-Loader源码分析
前言
ImageLoader
是 android
使用中出现比较早(PS:即的刚接触安卓项目的时候就用的是这个图片加载图,算算已经快5年了),使用最多的一个开源图片加载库了。随着glide
, fresco
和 picasso
等图片加载的库出现,ImageLoader
使用变得越来越少。最近在看其他图片加载库的源码,顺便补补之前错过的一些事情。
代码仓库地址:Android-Universal-Image-Loader
ImageLoader
这个是 ImageLoader
的架构,ImageLader
图片加载库的主要组成部分都包括在其中。
下边这幅图对应的是,组成上面架构的每个部分的对应的类实现:
ImageLoader
:为ImageView
下载和展示图片的单例;DisplayImageOptions
: 图片展示的配置项(加载中、空url、加载失败默认图等);ImageLoaderConfiguration
:ImageLoader
的配置项;ImageAware
:表示图像感知视图,该视图提供了图像处理和显示所需的所有属性和行为;ImageLoadingListener
:监听图片加载进度,开始、失败、成功、取消;ImageLoaderEngine
:执行图片下载和展现任务;BitmapDisplayer
:展现Bitmap
在ImageView
上的时候可以修改这个Bitmap
或添加展示的动画效果;BitmapProcessor
:可以处理原始的Bitmap
;MemoryCache
:Bitmap
内存缓存接口;DiskCache
:磁盘缓存;ImageDecoder
:根据ImageDecodingInfo
信息得到图片并根据参数将其转换为 Bitmap。ImageDownloader
:通过URI
获取图片;DisplayBitmapTask
:展示图片并进行回调;ProcessAndDisplayImageTask
:处理图片和展现图片的任务,用于加载内存缓存中的图片;LoadAndDisplayImagTask
:处理加载和显示图像的任务,用于从Internet或文件系统加载图像为Bitmap
;
Config配置
初始化配置参数,参数configuration
为ImageLoader
的配置信息,包括图片最大尺寸、任务线程池、磁盘缓存、下载器、解码器等等。
ImageLoaderConfiguration{final Resources resources;//上下文环境中的resourcefinal int maxImageWidthForMemoryCache;//内存缓存最大宽度final int maxImageHeightForMemoryCache;//内存缓存最大高度final int maxImageWidthForDiskCache;//磁盘缓存最大宽度final int maxImageHeightForDiskCache;//磁盘缓存最大高度//在将图像保存到磁盘缓存之前先对其进行调整大小/压缩处理final BitmapProcessor processorForDiskCache;final Executor taskExecutor;//自定义图片加载和展现的线程池final Executor taskExecutorForCachedImages;//自定义展现在磁盘上的图片的线程池final boolean customExecutor;//是否自定义下载的线程池final boolean customExecutorForCachedImages;//是否自定义缓存图片的线程池//默认核心线程数和线程池容量为3final int threadPoolSize;//默认的线程优先级低两级final int threadPriority;//LIFO,FIFO;默认为先进先出FIFOfinal QueueProcessingType tasksProcessingType;//内存缓存,默认为MemoryClass的八分之一,3.0之后为LargeMemoryClass的八分之一//如果开启denyCacheImageMultipleSizesInMemory,那么缓存为FuzzyKeyMemoryCache实例,只判断图片地址不判断大小,如果相同那么刷新缓存final MemoryCache memoryCache;//LruDiskCache,大小默认存储为Long.MAX_VALUE,默认最大数量为Long.MAX_VALUE;final DiskCache diskCache;//通过URI从网络或文件系统或应用程序资源中检索图像final ImageDownloader downloader;//将图像解码为Bitmap,将其缩放到所需大小final ImageDecoder decoder;//包含图像显示选项(默认图设置以及其他默认选项)final DisplayImageOptions defaultDisplayImageOptions;//网络禁止下载器,一般不直接应用final ImageDownloader networkDeniedDownloader;//在慢速网络上处理下载final ImageDownloader slowNetworkDownloader;
}
还有一个对于某个ImageView
进行展示设置的 DisplayImageOptions
,配置图片显示的配置项。比如加载前、加载中、加载失败应该显示的占位图片,图片是否需要在磁盘缓存,是否需要在内存缓存等。
视图
讲视图主要是想让ImageView
与 ImageLoader
联系在一起来,ImageLoader
通过 ImageAware
接口实现图片在视图上的展现。
public interface ImageAware {int getWidth();int getHeight();ViewScaleType getScaleType();View getWrappedView();boolean isCollected();int getId();boolean setImageDrawable(Drawable drawable);boolean setImageBitmap(Bitmap bitmap);
}
- ImageAware->ViewAware
- ImageAware->ViewAware->ImageViewAware
- ImageAware->NonViewAware
其中 ViewAware
是抽象类,所以 ImageAware
只有 ImageViewAware
和 NonViewAware
两个实现类。
NonViewAware
提供处理原始图像所需的信息,但不显示图像。当用户只需要加载和解码图像的时候可以使用它。
加载回调
主要进行图片加载过程中的事件监听。
public interface ImageLoadingListener {//开始加载void onLoadingStarted(String imageUri, View view);//加载失败void onLoadingFailed(String imageUri, View view, FailReason failReason);//加载完成void onLoadingComplete(String imageUri, View view, Bitmap loadedImage);//取消加载void onLoadingCancelled(String imageUri, View view);
}
图片展示
在ImageAware
中显示bitmap
对象的接口。可在实现中对 bitmap
做一些额外处理,比如加圆角、动画效果。
默认的BitmapDisplay
是 SimpleBitmapDisplayer
仅仅实现了加载图片的功能,ImageLoader
还提供了CircleBitmapDisplayer
、FadeInBitmapDisplayer
和 RoundedBitmapDisplayer
等其他的实现。
public interface BitmapDisplayer {void display(Bitmap bitmap, ImageAware imageAware, LoadedFrom loadedFrom);
}
public final class SimpleBitmapDisplayer implements BitmapDisplayer {@Overridepublic void display(Bitmap bitmap, ImageAware imageAware, LoadedFrom loadedFrom) {imageAware.setImageBitmap(bitmap);}
}
位图处理
图片处理接口。可用于对图片预处理(Pre-process
)和后处理(Post-process
),这两个处理器的配置都是在DisplayImageOptions
进行设置。其中预处理是在图片获取完缓存之前处理,后端处理是指在展示前的处理。
public interface BitmapProcessor {Bitmap process(Bitmap bitmap);
}
内存缓存
内存缓存的是Bitmap
,默认的缓存容器是LruMemoryCache
。内存缓存的Bitmap
都是通过数据流解码生成的。
public interface MemoryCache {boolean put(String key, Bitmap value);Bitmap get(String key);Bitmap remove(String key);Collection<String> keys();void clear();
}
public static MemoryCache createMemoryCache(Context context, int memoryCacheSize) {if (memoryCacheSize == 0) {ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);int memoryClass = am.getMemoryClass();if (hasHoneycomb() && isLargeHeap(context)) {memoryClass = getLargeMemoryClass(am);}memoryCacheSize = 1024 * 1024 * memoryClass / 8;}return new LruMemoryCache(memoryCacheSize);
}
LruMemoryCache
是区分size的,如果ImageLoaderConfiguration
设置 denyCacheImageMultipleSizesInMemory
那么缓存为 FuzzyKeyMemoryCache
实例,只判断图片地址不判断大小,如果相同那么刷新缓存。 FuzzyKeyMemoryCache
只是重写了MemoryCache
的 put
方法。
图片解码器
根据ImageDecodingInfo
信息得到图片并根据参数将其转换为 Bitmap
。
public interface ImageDecoder {Bitmap decode(ImageDecodingInfo imageDecodingInfo) throws IOException;
}
public static ImageDecoder createImageDecoder(boolean loggingEnabled) {return new BaseImageDecoder(loggingEnabled);
}
BaseImageDecoder
是ImageLoaderConfiguration
默认的解码器。
public class BaseImageDecoder implements ImageDecoder {@Overridepublic Bitmap decode(ImageDecodingInfo decodingInfo) throws IOException {Bitmap decodedBitmap;ImageFileInfo imageInfo;//通过ImageDecodingInfo中的信息获取数据流,图片下载器部分会讲怎么获取数据流InputStream imageStream = getImageStream(decodingInfo);if (imageStream == null) {L.e(ERROR_NO_IMAGE_STREAM, decodingInfo.getImageKey());return null;}try {//确定图片尺寸和旋转角度,生成图片文件信息imageInfo = defineImageSizeAndRotation(imageStream, decodingInfo);//数据流的游标重置imageStream = resetStream(imageStream, decodingInfo);//生成控制Bitmap进行采样的OptionOptions decodingOptions = prepareDecodingOptions(imageInfo.imageSize, decodingInfo);//将输入流解码为位图decodedBitmap = BitmapFactory.decodeStream(imageStream, null, decodingOptions);} finally {IoUtils.closeSilently(imageStream);}if (decodedBitmap == null) {L.e(ERROR_CANT_DECODE_IMAGE, decodingInfo.getImageKey());} else {//对Bitmmap进行缩放和旋转decodedBitmap = considerExactScaleAndOrientatiton(decodedBitmap, decodingInfo, imageInfo.exif.rotation,imageInfo.exif.flipHorizontal);}return decodedBitmap;}/****部分代码省略***/
}
磁盘缓存
本地图片缓存,可向本地磁盘缓存保存图片或从本地磁盘读取图片。LruDiskCache
是ImageLoaderConfiguration
默认的磁盘缓存容器。这次缓存的图片文件都是通过InputStream
保存在磁盘上的,实现是通过调用 save
方法。
public interface DiskCache {File getDirectory();File get(String imageUri);boolean save(String imageUri, InputStream imageStream, IoUtils.CopyListener listener) throws IOException;boolean save(String imageUri, Bitmap bitmap) throws IOException;boolean remove(String imageUri);void close();void clear();
}
public static DiskCache createDiskCache(Context context, FileNameGenerator diskCacheFileNameGenerator,long diskCacheSize, int diskCacheFileCount) {File reserveCacheDir = createReserveDiskCacheDir(context);if (diskCacheSize > 0 || diskCacheFileCount > 0) {///Android/data/[app_package_name]/cache/uil-imagesFile individualCacheDir = StorageUtils.getIndividualCacheDirectory(context);try {//缓存目录,缓存大小,缓存数量,缓存文件名生成器都不能为空return new LruDiskCache(individualCacheDir, reserveCacheDir, diskCacheFileNameGenerator, diskCacheSize,diskCacheFileCount);} catch (IOException e) {L.e(e);// continue and create unlimited cache}}File cacheDir = StorageUtils.getCacheDirectory(context);//UnlimitedDiskCache大小没有限制return new UnlimitedDiskCache(cacheDir, reserveCacheDir, diskCacheFileNameGenerator);
}
网络下载
获取Uri
对应的 Stream
, extra
为辅助的下载器,可以通过DisplayImageOptions
得到extraForDownloader
。下载主要有http
、https
、file
、content
、assets
和 drawable
。
public interface ImageDownloader {InputStream getStream(String imageUri, Object extra) throws IOException;/** Represents supported schemes(protocols) of URI. Provides convenient methods for work with schemes and URIs. */public enum Scheme {HTTP("http"), HTTPS("https"), FILE("file"), CONTENT("content"), ASSETS("assets"), DRAWABLE("drawable"), UNKNOWN("");private String scheme;private String uriPrefix;Scheme(String scheme) {this.scheme = scheme;uriPrefix = scheme + "://";}/***部分代码省略***/}
}
BaseImageDownloader
为默认的下载器:内部通过下载资源的类型的不同有着不同的实现。
public class BaseImageDownloader implements ImageDownloader {@Overridepublic InputStream getStream(String imageUri, Object extra) throws IOException {switch (Scheme.ofUri(imageUri)) {case HTTP:case HTTPS:return getStreamFromNetwork(imageUri, extra);case FILE:return getStreamFromFile(imageUri, extra);case CONTENT:return getStreamFromContent(imageUri, extra);case ASSETS:return getStreamFromAssets(imageUri, extra);case DRAWABLE:return getStreamFromDrawable(imageUri, extra);case UNKNOWN:default:return getStreamFromOtherSource(imageUri, extra);}}/***部分代码省略***/
}
看一个从网络请求中获取Stream
的实现:
public class BaseImageDownloader implements ImageDownloader {protected InputStream getStreamFromNetwork(String imageUri, Object extra) throws IOException {//根据imageUri,创建HttpURLConnection对象HttpURLConnection conn = createConnection(imageUri, extra);int redirectCount = 0;//最多重定向请求5次while (conn.getResponseCode() / 100 == 3 && redirectCount < MAX_REDIRECT_COUNT) {conn = createConnection(conn.getHeaderField("Location"), extra);redirectCount++;}InputStream imageStream;try {imageStream = conn.getInputStream();} catch (IOException e) {// Read all data to allow reuse connection (http://bit.ly/1ad35PY)IoUtils.readAndCloseStream(conn.getErrorStream());throw e;}//如果responseCode不是200那么关闭请求抛出IO异常if (!shouldBeProcessed(conn)) {IoUtils.closeSilently(imageStream);throw new IOException("Image request failed with response code " + conn.getResponseCode());}return new ContentLengthInputStream(new BufferedInputStream(imageStream, BUFFER_SIZE), conn.getContentLength());}
}
ImageLoader
讲完了组成的ImageLoader
的一整套图片加载流程的没个部分:网络下载、磁盘缓存、数据解码、内存缓存、位图处理、图片展示和业务回调。下面我们看看ImageLoader
是怎么将这些部分是怎么串在一起的。
使用双重校验锁(DCL:double-checked locking)实现单例操作 Java版的7种单例模式。
public class ImageLoader {private ImageLoaderConfiguration configuration;//图片加载配置信息private ImageLoaderEngine engine;//图片加载引擎private ImageLoadingListener defaultListener = new SimpleImageLoadingListener();//默认的回调监听private volatile static ImageLoader instance;//单例/** Returns singleton class instance */public static ImageLoader getInstance() {if (instance == null) {synchronized (ImageLoader.class) {if (instance == null) {instance = new ImageLoader();}}}return instance;}//初始化方法public synchronized void init(ImageLoaderConfiguration configuration) {if (configuration == null) {throw new IllegalArgumentException(ERROR_INIT_CONFIG_WITH_NULL);}if (this.configuration == null) {L.d(LOG_INIT_CONFIG);engine = new ImageLoaderEngine(configuration);this.configuration = configuration;} else {L.w(WARNING_RE_INIT_CONFIG);}}/***其他代码省略***/
}
上面代码是 ImageLoader
的构造初始化方法,接下分析它加载图片时候的调用:
public class ImageLoader {public void displayImage(String uri, ImageView imageView) {displayImage(uri, new ImageViewAware(imageView), null, null, null);}//最终加载图片的方法public void displayImage(String uri, ImageAware imageAware, DisplayImageOptions options,ImageSize targetSize, ImageLoadingListener listener, ImageLoadingProgressListener progressListener) {//校验配置是否为空checkConfiguration();if (imageAware == null) {throw new IllegalArgumentException(ERROR_WRONG_ARGUMENTS);}//添加默认的空回调if (listener == null) {listener = defaultListener;}//添加默认的图片展示配置if (options == null) {options = configuration.defaultDisplayImageOptions;}//下载地址为空if (TextUtils.isEmpty(uri)) {engine.cancelDisplayTaskFor(imageAware);//取消对于当前imageAware的展示任务listener.onLoadingStarted(uri, imageAware.getWrappedView());//回调展示开始//展示配置中有处理为空的url的默认图if (options.shouldShowImageForEmptyUri()) {//给imageAware设置这个默认图imageAware.setImageDrawable(options.getImageForEmptyUri(configuration.resources));} else {imageAware.setImageDrawable(null);}listener.onLoadingComplete(uri, imageAware.getWrappedView(), null);//回调展示结束return;}//获取当前需要下载的图片的sizeif (targetSize == null) {targetSize = ImageSizeUtils.defineTargetSizeForView(imageAware, configuration.getMaxImageSize());}//获取内存缓存的key(url_width_height)String memoryCacheKey = MemoryCacheUtils.generateKey(uri, targetSize);//添加到执行引擎cacheKeysForImageAwares的容器中engine.prepareDisplayTaskFor(imageAware, memoryCacheKey);listener.onLoadingStarted(uri, imageAware.getWrappedView());//回调展示开始//从内存中获取缓存的memoryCacheKey对应的bitmapBitmap bmp = configuration.memoryCache.get(memoryCacheKey);//bitmap不为空,而且没有被回收if (bmp != null && !bmp.isRecycled()) {L.d(LOG_LOAD_IMAGE_FROM_MEMORY_CACHE, memoryCacheKey);//如果需要展示加载的进度,默认是不设置BitmapProcessor处理器的if (options.shouldPostProcess()) {//构造图片加载信息ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey,options, listener, progressListener, engine.getLockForUri(uri));//构造处理展示图片的任务ProcessAndDisplayImageTask displayTask = new ProcessAndDisplayImageTask(engine, bmp, imageLoadingInfo,defineHandler(options));//如果需要同步加载if (options.isSyncLoading()) {displayTask.run();//直接进行展现任务} else {engine.submit(displayTask);//提交任务到加载引擎中}} else {//从内存中加载bitmap设置给imageAware,options.getDisplayer().display(bmp, imageAware, LoadedFrom.MEMORY_CACHE);//回调加载完成listener.onLoadingComplete(uri, imageAware.getWrappedView(), bmp);}} else {//如果需要展示加载的进度if (options.shouldShowImageOnLoading()) {//展示默认的加载中的图片imageAware.setImageDrawable(options.getImageOnLoading(configuration.resources));} else if (options.isResetViewBeforeLoading()) {imageAware.setImageDrawable(null);}//构造图片加载信息ImageLoadingInfo imageLoadingInfo = new ImageLoadingInfo(uri, imageAware, targetSize, memoryCacheKey,options, listener, progressListener, engine.getLockForUri(uri));//构造加载展示图片的任务LoadAndDisplayImageTask displayTask = new LoadAndDisplayImageTask(engine, imageLoadingInfo,defineHandler(options));//如果需要同步加载if (options.isSyncLoading()) {displayTask.run();//直接进行展现任务} else {engine.submit(displayTask);//提交任务到加载引擎中}}}/***其他代码省略***/
}
Imageloader
图片加载流程叙述:
- 校验配置;
- 赋值默认值(回调监听、图片展现配置);
- 判断下载地址为空;
3.1. 取消当前imageAware的图片展示任务;
3.2. 如果图片展示配置有url为空的默认处理图那么加载默认图;- 获取当前需要加载图的size;
- 获取缓存的key
5.1. 根据key从内存缓存中获取bitmap,且bitmap有效;
5.1.1. 如果需要展现加载进度,那么构造处理图片展示任务(ProcessAndDisplayImageTask)并执行(如果展现需要同步那么直接展示,否则任务提交到线程池);
5.1.2. 否则直接加载bitmap给当前的imageAware;
5.2. 如果需要展现加载进度,那么获取图片展示配置中的加载状态资源进行展示,准备下一步加载真实图片资源;
5.2.1. 构造加载展示图片任务(LoadAndDisplayImageTask)并执行(如果展现需要同步那么直接展示,否则任务提交到线程池);
图片加载引擎
虽然叫做图片加载引起,但其实它仅仅只是一个任务分发处理器,负责分发LoadAndDisplayImageTask
和ProcessAndDisplayImageTask
给具体的线程池去执行,以及任务的暂停等操作。
class ImageLoaderEngine {final ImageLoaderConfiguration configuration;//图片加载配置信息private Executor taskExecutor;//configuration.taskExecutorprivate Executor taskExecutorForCachedImages;//configuration.taskExecutorForCachedImagesprivate Executor taskDistributor;//分配任务的线程池为newCachedThreadPool//imageview的hashcode和下载的key(url_width_height)private final Map<Integer, String> cacheKeysForImageAwares = Collections.synchronizedMap(new HashMap<Integer, String>());private final Map<String, ReentrantLock> uriLocks = new WeakHashMap<String, ReentrantLock>();private final AtomicBoolean paused = new AtomicBoolean(false);private final AtomicBoolean networkDenied = new AtomicBoolean(false);private final AtomicBoolean slowNetwork = new AtomicBoolean(false); private final Object pauseLock = new Object();ImageLoaderEngine(ImageLoaderConfiguration configuration) {this.configuration = configuration;taskExecutor = configuration.taskExecutor;taskExecutorForCachedImages = configuration.taskExecutorForCachedImages;taskDistributor = DefaultConfigurationFactory.createTaskDistributor();}/***其他代码省略***/
}
任务提交处理,主要做了不同类型的任务分发给对应的任务执行的线程池:
class ImageLoaderEngine {/** Submits task to execution pool *///执行从磁盘获取和网络上加载图片的任务void submit(final LoadAndDisplayImageTask task) {taskDistributor.execute(new Runnable() {@Overridepublic void run() {File image = configuration.diskCache.get(task.getLoadingUri());//是否已经缓存在磁盘上boolean isImageCachedOnDisk = image != null && image.exists();initExecutorsIfNeed();if (isImageCachedOnDisk) {taskExecutorForCachedImages.execute(task);} else {taskExecutor.execute(task);}}});}/** Submits task to execution pool *///支持从缓存中加载图片的任务void submit(ProcessAndDisplayImageTask task) {initExecutorsIfNeed();taskExecutorForCachedImages.execute(task);}//任务线程池是否关闭,关闭则重新创建private void initExecutorsIfNeed() {if (!configuration.customExecutor && ((ExecutorService) taskExecutor).isShutdown()) {taskExecutor = createTaskExecutor();}if (!configuration.customExecutorForCachedImages && ((ExecutorService) taskExecutorForCachedImages).isShutdown()) {taskExecutorForCachedImages = createTaskExecutor();}}//创建任务线程池private Executor createTaskExecutor() {return DefaultConfigurationFactory.createExecutor(configuration.threadPoolSize, configuration.threadPriority,configuration.tasksProcessingType);}/***其他代码省略***/
}
从ImageLoader
的displayImage
方法实现和 ImageLoaderEngine
的任务分发可以看出来,ImageLoader
主要有两种类型的任务 ProcessAndDisplayImageTask
和 LoadAndDisplayImageTask
。
处理和展示图片任务
final class ProcessAndDisplayImageTask implements Runnable {/***部分代码省略***/@Overridepublic void run() {L.d(LOG_POSTPROCESS_IMAGE, imageLoadingInfo.memoryCacheKey);//获取图片展现配置中的图片处理器BitmapProcessor processor = imageLoadingInfo.options.getPostProcessor();//获取处理过后的BiamtpBitmap processedBitmap = processor.process(bitmap); DisplayBitmapTask displayBitmapTask = new DisplayBitmapTask(processedBitmap, imageLoadingInfo, engine,LoadedFrom.MEMORY_CACHE);//如果isSyncLoading那么调用displayBitmapTask的run方法,否则如果handler不为空切换到主线程执行displayBitmapTask.runLoadAndDisplayImageTask.runTask(displayBitmapTask, imageLoadingInfo.options.isSyncLoading(), handler, engine);}
}
加载和展示图片任务
先看LoadAndDisplayImageTask.runTask
方法:
static void runTask(Runnable r, boolean sync, Handler handler, ImageLoaderEngine engine) {if (sync) {//如果需要同步那么在当前线程执行r.run();} else if (handler == null) {//handler为空切换线程到taskDistributor线程池中执行engine.fireCallback(r);} else {handler.post(r);//切换到handler主线程执行}
}
run
final class LoadAndDisplayImageTask implements Runnable, IoUtils.CopyListener {/***部分代码省略***/@Overridepublic void run() {//如果ImageLoader暂停执行任务(ImageLoader.pause方法被调用),那么当前线程进入等待被唤醒(ImageLoader.resume方法被调用);//否则校验当前任务是否有效(校验目标ImageAware是否已经被回收,或者ImageAware需要加载的uri已经不是当前的uri)if (waitIfPaused()) return;//是否需要延迟加载(图片展示配置中如果delayBeforeLoading时间大于0)////否则校验当前任务是否有效(校验目标ImageAware是否已经被回收,或者ImageAware需要加载的uri已经不是当前的uri)if (delayIfNeed()) return;//获取当前图片加载任务的锁ReentrantLock loadFromUriLock = imageLoadingInfo.loadFromUriLock;L.d(LOG_START_DISPLAY_IMAGE_TASK, memoryCacheKey);if (loadFromUriLock.isLocked()) {L.d(LOG_WAITING_FOR_IMAGE_LOADED, memoryCacheKey);}loadFromUriLock.lock();Bitmap bmp;try {//校验目标ImageAware是否已经被回收,或者ImageAware需要加载的uri已经不是当前的uricheckTaskNotActual();//先从内存缓存中获取对应的Bitmapbmp = configuration.memoryCache.get(memoryCacheKey);//如果bitmap被回收或者为空if (bmp == null || bmp.isRecycled()) {//尝试加载Bitmap(磁盘、资源、网络等)bmp = tryLoadBitmap();//加载失败直接返回if (bmp == null) return; // listener callback already was fired//校验目标ImageAware是否已经被回收,或者ImageAware需要加载的uri已经不是当前的uricheckTaskNotActual();//检验是否当前线程被打断checkTaskInterrupted();//根据图片展示配置项是否要进行保存前处理if (options.shouldPreProcess()) {L.d(LOG_PREPROCESS_IMAGE, memoryCacheKey);bmp = options.getPreProcessor().process(bmp);if (bmp == null) {L.e(ERROR_PRE_PROCESSOR_NULL, memoryCacheKey);}}//是否需要对这个Bitmap进行内存缓存if (bmp != null && options.isCacheInMemory()) {L.d(LOG_CACHE_IMAGE_IN_MEMORY, memoryCacheKey);configuration.memoryCache.put(memoryCacheKey, bmp);}} else {loadedFrom = LoadedFrom.MEMORY_CACHE;L.d(LOG_GET_IMAGE_FROM_MEMORY_CACHE_AFTER_WAITING, memoryCacheKey);}//根据图片展示配置项是否要进行展示前处理if (bmp != null && options.shouldPostProcess()) {L.d(LOG_POSTPROCESS_IMAGE, memoryCacheKey);bmp = options.getPostProcessor().process(bmp);if (bmp == null) {L.e(ERROR_POST_PROCESSOR_NULL, memoryCacheKey);}}//校验目标ImageAware是否已经被回收,或者ImageAware需要加载的uri已经不是当前的uricheckTaskNotActual();//检验是否当前线程被打断checkTaskInterrupted();} catch (TaskCancelledException e) {//进行失败处理fireCancelEvent();return;} finally {//释放锁loadFromUriLock.unlock();}//执行展示图片任务此处和ProcessAndDisplayImageTask任务后的展示逻辑相同DisplayBitmapTask displayBitmapTask = new DisplayBitmapTask(bmp, imageLoadingInfo, engine, loadedFrom);runTask(displayBitmapTask, syncLoading, handler, engine);}/***部分代码省略***/
}
任务是否有效:校验目标ImageAware
是否已经被回收,或者ImageAware
需要加载的uri
已经不是当前的uri
(被取消或者被代替)。
- 校验
ImageLoader
是否暂停执行任务和当前的任务是否有效;- 是否需要进行延迟加载,延迟加载后校验当前是否任务有效;
- 获取当前图片加载任务的锁进行上锁;
- 校验当前是否任务有效后开始进行
Bitmap
获取;
4.1 先从内存缓存中获取对应的Bitmap
;
4.2 获取Bitmap
为空获取已经被回收那么尝试加载Bitmap
;
4.2.1Bitmap
加载失败直接返回;
4.2.2 校验当前是否任务有效;
4.2.3 检验是否当前线程被打断;
4.2.4 根据图片展示配置项是否要进行保存前处理;
4.2.5 是否需要对这个Bitmap
进行内存缓存;
4.3 根据图片展示配置项是否要进行展示前处理
4.4 校验当前是否任务有效;
4.5 检验是否当前线程被打断;- 释放锁;
- 执行展示图片任务;
加载图片
final class LoadAndDisplayImageTask implements Runnable, IoUtils.CopyListener {/***部分代码省略***/private Bitmap tryLoadBitmap() throws TaskCancelledException {Bitmap bitmap = null;try {File imageFile = configuration.diskCache.get(uri);//从磁盘获取存储的图片if (imageFile != null && imageFile.exists() && imageFile.length() > 0) {L.d(LOG_LOAD_IMAGE_FROM_DISK_CACHE, memoryCacheKey);loadedFrom = LoadedFrom.DISC_CACHE;//校验目标ImageAware是否已经被回收,或者ImageAware需要加载的uri已经不是当前的uricheckTaskNotActual();bitmap = decodeImage(Scheme.FILE.wrap(imageFile.getAbsolutePath()));//进行图片解码}//bitmap为空,或者长宽小于0重新进行数据获取if (bitmap == null || bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) {L.d(LOG_LOAD_IMAGE_FROM_NETWORK, memoryCacheKey);loadedFrom = LoadedFrom.NETWORK;String imageUriForDecoding = uri;//是否需要缓存在磁盘上,如果需要进行磁盘缓存if (options.isCacheOnDisk() && tryCacheImageOnDisk()) {imageFile = configuration.diskCache.get(uri);if (imageFile != null) {imageUriForDecoding = Scheme.FILE.wrap(imageFile.getAbsolutePath());}}//校验目标ImageAware是否已经被回收,或者ImageAware需要加载的uri已经不是当前的uricheckTaskNotActual();bitmap = decodeImage(imageUriForDecoding);//进行图片解码//bitmap为空,或者长宽小于0进行异常处理if (bitmap == null || bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) {fireFailEvent(FailType.DECODING_ERROR, null);}}} catch (){/***异常处理省略***/}return bitmap;}/***部分代码省略***/
}
缓存图片到磁盘
final class LoadAndDisplayImageTask implements Runnable, IoUtils.CopyListener {/***部分代码省略***/private boolean tryCacheImageOnDisk() throws TaskCancelledException {L.d(LOG_CACHE_IMAGE_ON_DISK, memoryCacheKey);boolean loaded;try {loaded = downloadImage();//下载图片,缓存到磁盘if (loaded) {int width = configuration.maxImageWidthForDiskCache;int height = configuration.maxImageHeightForDiskCache;if (width > 0 || height > 0) {L.d(LOG_RESIZE_CACHED_IMAGE_FILE, memoryCacheKey);//设置图片的大小,重新保存到磁盘resizeAndSaveImage(width, height); // TODO : process boolean result}}} catch (IOException e) {L.e(e);loaded = false;}return loaded;}private boolean downloadImage() throws IOException {//通过download获取数据流InputStream is = getDownloader().getStream(uri, options.getExtraForDownloader());if (is == null) {L.e(ERROR_NO_IMAGE_STREAM, memoryCacheKey);return false;} else {try {//保存到磁盘return configuration.diskCache.save(uri, is, this);} finally {IoUtils.closeSilently(is);}}}/***部分代码省略***/
}
其他
- 取消当前
imageview
对应的任务
public void cancelDisplayTask(ImageView imageView) {engine.cancelDisplayTaskFor(new ImageViewAware(imageView));
}
- 拒绝或允许
ImageLoader
从网络下载图像
public void denyNetworkDownloads(boolean denyNetworkDownloads) {engine.denyNetworkDownloads(denyNetworkDownloads);
}
- 设置
ImageLoader
是否使用FlushedInputStream
进行网络下载的选项
public void handleSlowNetwork(boolean handleSlowNetwork) {engine.handleSlowNetwork(handleSlowNetwork);
}
- 暂停ImageLoader。在ImageLoader#resume恢复之前,不会执行所有新的“加载和显示”任务。
- 已经运行的任务不会暂停。
public void pause() {engine.pause();
}
- 恢复等待的“加载和显示”任务
public void resume() {engine.resume();
}
- 取消所有正在运行和计划的显示图像任务
- 还可以继续使用
ImageLoader
public void stop() {engine.stop();
}
- 取消所有正在运行和计划的显示图像任务
- 销毁所有配置,重新使用ImageLoader需要进行初始化
public void destroy() {if (configuration != null) L.d(LOG_DESTROY);stop();configuration.diskCache.close();engine = null;configuration = null;
}
- 为了更友好的用户体验,在列表滑动过程中可以暂停加载(调用
pause
和resume
); - RGB_565代替ARGB_8888,减少占用内存;
- 使用
memoryCache(new WeakMemoryCache())
将内存中的Bitmap
变为软引用;
文章到这里就全部讲述完啦,若有其他需要交流的可以留言哦!!
想阅读作者的更多文章,可以查看我 个人博客 和公共号:
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- H.264流媒体协议格式中的Annex B格式和AVCC格式深度解析
原文链接:https://blog.csdn.net/Romantic_Energy/article/details/50508332版权声明:本文为CSDN博主「Chucky_Hu」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/Romantic_Energy/article/details/50508332本…...
2024/4/25 19:06:55 - 信息检索研究与开发国际会议SIGIR 2020于西安召开!摘要截止日期为1月15日!
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/ConferenceEye/article/details/103256666关注“会议之眼”,第一时间送达 会议之眼A类,CCF A类信息检索研究与开发国际会…...
2024/4/25 15:55:11 - 国标GB/T28181协议下EasyGBS互联网无插件视频播放器起播慢或延迟高问题解决方案
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/EasyGBS/article/details/100983126引言28181协议全称为GB/T28181《安全防范视频监控联网系统信息传输、交换、控制技术要求…...
2024/4/26 16:42:18 - 夜光带你走进C# 游戏开发等(八十四)擅长的领域
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/weixin_41987706/article/details/103194048夜光序言:如果人生永远是一条直路,那一定很单调;如果人生永远停留在某个阶段…...
2024/4/27 0:37:11 - 夜光带你走进C# 游戏开发等(八十五)擅长的领域
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/weixin_41987706/article/details/103194489夜光序言:不要问, 雨, 为何如此凄凉? 那天,诗人独自忧伤,没有日落的帷幕…...
2024/4/23 18:25:56 - (C语言)求1-n的阶乘之和
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/hua12ng/article/details/103256838求1-n的阶乘之和 题目:输入正整数n(1-10),求1-n的阶乘之和,最后必须输出回车。遇到…...
2024/4/19 18:01:34 - Hadoop的集群安装
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/u010395024/article/details/103256897今天开始hadoop学习。一开虚拟机就出现各种状况。状况一vim 编辑器出现中文乱码。 …...
2024/4/20 4:43:57 - Python的安装及环境变量配置
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/xiaoyaGrace/article/details/1032569211.去python官网下载安装镜像,地址:https://www.python.org/downloads/Python的安…...
2024/4/27 5:18:17 - 阅读笔记(TIP2019)Subjective and Objective Quality Assessment of Stitched Images for Virtual Reality
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/Miracle0_0/article/details/103256950#2019年11月26日...
2024/4/25 23:14:50 - 推导投影矩阵
原文链接:https://www.codeguru.com/cpp/misc/misc/graphics/article.php/c10123/Deriving-Projection-Matrices.htm#page-3参考:添加链接描述 在任何3D图形程序员工具包中的基本矩阵变换中,投影矩阵都更为复杂。一眼就能理解平移和缩放,任何对三角学有基本了解的人都可以想…...
2024/4/26 14:31:21 - redis desktop manager安装以及使用教程
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/luanzongke5704/article/details/1032569791.下载redis desktop manager 版本0.9.99 官网下载: https://redisdesktop.com…...
2024/4/25 12:38:28 - EVS(Enhance Voice Services) Codec 增强语音服务编码
原文链接:https://blog.csdn.net/shij19/article/details/52946592一、什么是EVS 当前视频业务有标清、高清、超清、1080P等等技术,不断在增强视频清晰度,语音业务为了增强清晰度从2G时代的NB(窄带)通信到目前3G和4G在用的WB(宽带)通信。语音业务和视频业务一样,在WB宽带通…...
2024/4/22 2:07:08 - Netty-粘包,半包和使用Json方式传输数据
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/qq1010234991/article/details/103257013文章目录JSON和ProtoBuf序列化背景详解粘包和拆包粘包和半包半包问题的实践案例运…...
2024/4/26 4:57:58 - java线程池-异步
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/weixin_43166227/article/details/103176689进程与线程 进程:一个正在运行的应用程序在操作系统中被称为一个进程,进程包…...
2024/4/18 16:25:11 - python_数据筛选查询
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/wj1298250240/article/details/103257043python_数据筛选查询 #显示使用了优惠券消费的商品,正样本 t2 = merchant3[(merc…...
2024/4/26 14:42:37 - git&github操作流程
版权声明:本文为博主原创文章,遵循 CC 4.0 BY 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/XiaoJiang0505/article/details/103256982Administrator@XPWY-41-WJW MINGW64 ~/Desktop $ pwd /c/Users/Administrator/Deskt…...
2024/4/26 1:51:53 - 条款05:了解C++默默编写并调用哪些函数——64
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/HCCQ1/article/details/103257139文章目录总结——67 主要内容如总结中所讲。 总结——67 编译器可以暗自为class创建默认构…...
2024/4/26 20:46:09 - windows7上使用docker容器
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/heima201907/article/details/1032571481.安装下载DockerToolbox,并安装。 下载地址:https://dn-dao-github-irror.daoc…...
2024/4/27 7:00:32 - angluarjs后台模板
我们为您提供关于angluarjs后台模板的精彩内容,我们为您分享本站的原创内容,我们还提供关于angluarjs后台模板的经验内容。...
2024/4/26 18:14:56
最新文章
- swagger xss漏洞复现
swagger xss漏洞复现 文章目录 swagger xss漏洞复现漏洞介绍影响版本实现原理漏洞复现修复建议: 漏洞介绍 Swagger UI 有一个有趣的功能,允许您提供 API 规范的 URL - 一个 yaml 或 json 文件,将被获取并显示给用户 根本原因非常简单 - 一个过时的库Dom…...
2024/4/27 10:43:07 - 梯度消失和梯度爆炸的一些处理方法
在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...
2024/3/20 10:50:27 - __dirname 在ES模块中的使用
前言 ECMAScript模块是 JavaScript 的新标准格式。在Node.js中越来越多的库逐渐从从CommonJS转移到ES模块 注:这里是指“真”ES 模块并不是指代码中 Node.js 中使用 import 写法但是实际被 tsc 转成 commonJS 的形式 但是Node.js ES 开发中此前有一个棘手的问题是获…...
2024/4/26 5:04:45 - 是否有替代U盘,可安全交换的医院文件摆渡方案?
医院内部网络存储着大量的敏感医疗数据,包括患者的个人信息、病历记录、诊断结果等。网络隔离可以有效防止未经授权的访问和数据泄露,确保这些敏感信息的安全。随着法律法规的不断完善,如《网络安全法》、《个人信息保护法》等,医…...
2024/4/23 23:05:24 - 【外汇早评】美通胀数据走低,美元调整
原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...
2024/4/26 18:09:39 - 【原油贵金属周评】原油多头拥挤,价格调整
原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...
2024/4/26 20:12:18 - 【外汇周评】靓丽非农不及疲软通胀影响
原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...
2024/4/26 23:05:52 - 【原油贵金属早评】库存继续增加,油价收跌
原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...
2024/4/27 4:00:35 - 【外汇早评】日本央行会议纪要不改日元强势
原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...
2024/4/25 18:39:22 - 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响
原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...
2024/4/25 18:39:22 - 【外汇早评】美欲与伊朗重谈协议
原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...
2024/4/26 21:56:58 - 【原油贵金属早评】波动率飙升,市场情绪动荡
原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...
2024/4/27 9:01:45 - 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试
原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...
2024/4/26 16:00:35 - 【原油贵金属早评】市场情绪继续恶化,黄金上破
原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...
2024/4/25 18:39:16 - 【外汇早评】美伊僵持,风险情绪继续升温
原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...
2024/4/25 18:39:16 - 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势
原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...
2024/4/26 19:03:37 - 氧生福地 玩美北湖(上)——为时光守候两千年
原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...
2024/4/26 22:01:59 - 氧生福地 玩美北湖(中)——永春梯田里的美与鲜
原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...
2024/4/25 18:39:14 - 氧生福地 玩美北湖(下)——奔跑吧骚年!
原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...
2024/4/26 23:04:58 - 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!
原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...
2024/4/25 2:10:52 - 「发现」铁皮石斛仙草之神奇功效用于医用面膜
原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...
2024/4/25 18:39:00 - 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者
原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...
2024/4/26 19:46:12 - 广州械字号面膜生产厂家OEM/ODM4项须知!
原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...
2024/4/25 18:38:58 - 械字号医用眼膜缓解用眼过度到底有无作用?
原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...
2024/4/27 8:32:30 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...
2022/11/19 21:17:16 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在iPhone上关闭“请勿打扰”
Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...
2022/11/19 21:16:57