/*******************************************************************************
|
* Copyright 2011-2014 Sergey Tarasevich
|
*
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
* you may not use this file except in compliance with the License.
|
* You may obtain a copy of the License at
|
*
|
* http://www.apache.org/licenses/LICENSE-2.0
|
*
|
* Unless required by applicable law or agreed to in writing, software
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* See the License for the specific language governing permissions and
|
* limitations under the License.
|
*******************************************************************************/
|
package com.nostra13.universalimageloader.core;
|
|
import android.annotation.TargetApi;
|
import android.app.ActivityManager;
|
import android.content.Context;
|
import android.content.pm.ApplicationInfo;
|
import android.os.Build;
|
import com.nostra13.universalimageloader.cache.disc.DiskCache;
|
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache;
|
import com.nostra13.universalimageloader.cache.disc.impl.ext.LruDiskCache;
|
import com.nostra13.universalimageloader.cache.disc.naming.FileNameGenerator;
|
import com.nostra13.universalimageloader.cache.disc.naming.HashCodeFileNameGenerator;
|
import com.nostra13.universalimageloader.cache.memory.MemoryCache;
|
import com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache;
|
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
|
import com.nostra13.universalimageloader.core.assist.deque.LIFOLinkedBlockingDeque;
|
import com.nostra13.universalimageloader.core.decode.BaseImageDecoder;
|
import com.nostra13.universalimageloader.core.decode.ImageDecoder;
|
import com.nostra13.universalimageloader.core.display.BitmapDisplayer;
|
import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;
|
import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
|
import com.nostra13.universalimageloader.core.download.ImageDownloader;
|
import com.nostra13.universalimageloader.utils.L;
|
import com.nostra13.universalimageloader.utils.StorageUtils;
|
|
import java.io.File;
|
import java.io.IOException;
|
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executors;
|
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadPoolExecutor;
|
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
/**
|
* Factory for providing of default options for {@linkplain ImageLoaderConfiguration configuration}
|
*
|
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
|
* @since 1.5.6
|
*/
|
public class DefaultConfigurationFactory {
|
|
/** Creates default implementation of task executor */
|
public static Executor createExecutor(int threadPoolSize, int threadPriority,
|
QueueProcessingType tasksProcessingType) {
|
boolean lifo = tasksProcessingType == QueueProcessingType.LIFO;
|
BlockingQueue<Runnable> taskQueue =
|
lifo ? new LIFOLinkedBlockingDeque<Runnable>() : new LinkedBlockingQueue<Runnable>();
|
return new ThreadPoolExecutor(threadPoolSize, threadPoolSize, 0L, TimeUnit.MILLISECONDS, taskQueue,
|
createThreadFactory(threadPriority, "uil-pool-"));
|
}
|
|
/** Creates default implementation of task distributor */
|
public static Executor createTaskDistributor() {
|
return Executors.newCachedThreadPool(createThreadFactory(Thread.NORM_PRIORITY, "uil-pool-d-"));
|
}
|
|
/** Creates {@linkplain HashCodeFileNameGenerator default implementation} of FileNameGenerator */
|
public static FileNameGenerator createFileNameGenerator() {
|
return new HashCodeFileNameGenerator();
|
}
|
|
/**
|
* Creates default implementation of {@link DiskCache} depends on incoming parameters
|
*/
|
public static DiskCache createDiskCache(Context context, FileNameGenerator diskCacheFileNameGenerator,
|
long diskCacheSize, int diskCacheFileCount) {
|
File reserveCacheDir = createReserveDiskCacheDir(context);
|
if (diskCacheSize > 0 || diskCacheFileCount > 0) {
|
File 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);
|
return new UnlimitedDiskCache(cacheDir, reserveCacheDir, diskCacheFileNameGenerator);
|
}
|
|
/** Creates reserve disk cache folder which will be used if primary disk cache folder becomes unavailable */
|
private static File createReserveDiskCacheDir(Context context) {
|
File cacheDir = StorageUtils.getCacheDirectory(context, false);
|
File individualDir = new File(cacheDir, "uil-images");
|
if (individualDir.exists() || individualDir.mkdir()) {
|
cacheDir = individualDir;
|
}
|
return cacheDir;
|
}
|
|
/**
|
* Creates default implementation of {@link MemoryCache} - {@link LruMemoryCache}<br />
|
* Default cache size = 1/8 of available app memory.
|
*/
|
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);
|
}
|
|
private static boolean hasHoneycomb() {
|
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
|
}
|
|
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
private static boolean isLargeHeap(Context context) {
|
return (context.getApplicationInfo().flags & ApplicationInfo.FLAG_LARGE_HEAP) != 0;
|
}
|
|
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
private static int getLargeMemoryClass(ActivityManager am) {
|
return am.getLargeMemoryClass();
|
}
|
|
/** Creates default implementation of {@link ImageDownloader} - {@link BaseImageDownloader} */
|
public static ImageDownloader createImageDownloader(Context context) {
|
return new BaseImageDownloader(context);
|
}
|
|
/** Creates default implementation of {@link ImageDecoder} - {@link BaseImageDecoder} */
|
public static ImageDecoder createImageDecoder(boolean loggingEnabled) {
|
return new BaseImageDecoder(loggingEnabled);
|
}
|
|
/** Creates default implementation of {@link BitmapDisplayer} - {@link SimpleBitmapDisplayer} */
|
public static BitmapDisplayer createBitmapDisplayer() {
|
return new SimpleBitmapDisplayer();
|
}
|
|
/** Creates default implementation of {@linkplain ThreadFactory thread factory} for task executor */
|
private static ThreadFactory createThreadFactory(int threadPriority, String threadNamePrefix) {
|
return new DefaultThreadFactory(threadPriority, threadNamePrefix);
|
}
|
|
private static class DefaultThreadFactory implements ThreadFactory {
|
|
private static final AtomicInteger poolNumber = new AtomicInteger(1);
|
|
private final ThreadGroup group;
|
private final AtomicInteger threadNumber = new AtomicInteger(1);
|
private final String namePrefix;
|
private final int threadPriority;
|
|
DefaultThreadFactory(int threadPriority, String threadNamePrefix) {
|
this.threadPriority = threadPriority;
|
group = Thread.currentThread().getThreadGroup();
|
namePrefix = threadNamePrefix + poolNumber.getAndIncrement() + "-thread-";
|
}
|
|
@Override
|
public Thread newThread(Runnable r) {
|
Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
|
if (t.isDaemon()) t.setDaemon(false);
|
t.setPriority(threadPriority);
|
return t;
|
}
|
}
|
}
|