diff --git a/README.md b/README.md index 2efadde4..d364c2b2 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,8 @@ Up to now,I have only write the demo of most parts of UI modules and View Inject UltimateAndroidUi project now has four separate ui projects:widget,component,animations and lollipop. So if you want to only use part of the ui project you can simply use the separate project. However if you want to use all of them, you can also use the UltimateAndroidUi project. +facebook/fresco is integrated into the framework,this provides a new image loading plan. Fresco is a powerful system for displaying images in Android applications. Fresco takes care of image loading and display, so you don't have to. It will load images from the network, local storage, or local resources, and display a placeholder until the image has arrived. It has two levels of cache; one in memory and another in internal storage. + [Update Log](https://github.com/cymcsg/UltimateAndroid/blob/master/updateLog.md) @@ -326,6 +328,72 @@ String imageUri = "drawable://" + R.drawable.image; // from drawables (only imag You can read the documents of [GreenDao](https://github.com/greenrobot/greenDAO) +7.A new scheme for display Images + + If you have already use or extend CommonApplication,you can use like this: + +``` //circle image and set a placeholder image + FrescoHelper.load(Uri.parse(imageUrl)) + .placeholder(CommonUtil.getDrawable(R.drawable.ic_image3)) + .circle() + .into(simple_drawee_view);``` + + Or for some advantage usage: + + FrescoHelper.load(Uri.parse(imageUrl)) + .placeholder(CommonUtil.getDrawable(R.drawable.ic_image3)) + .circle() + .into(simple_drawee_view, new ControllerListener() { + @Override + public void onSubmit(String s, Object o) { + ... + } + @Override + public void onFinalImageSet(String s, Object o, Animatable animatable) { + ... + } + @Override + public void onIntermediateImageSet(String s, Object o) { + ... + } + @Override + public void onIntermediateImageFailed(String s, Throwable throwable) { + ... + } + @Override + public void onFailure(String s, Throwable throwable) { + ... + } + @Override + public void onRelease(String s) { + ... + } + }, new Postprocessor() { + @Override + public CloseableReference process(Bitmap bitmap, PlatformBitmapFactory platformBitmapFactory) { + return null; + } + @Override + public String getName() { + return null; + } + @Override + public CacheKey getPostprocessorCacheKey() { + return null; + } + }); + +Acceptable URIs examples: + +``` java +String imageUri = "http://site.com/image.png"; // from Web +String imageUri = "https://static.pexels.com/photos/6789/flowers-petals-gift-flower-medium.jpg"; // from SSL Web +String imageUri = "file:///mnt/sdcard/image.png"; // from SD card +String imageUri = "content://media/external/audio/albumart/13"; // from content provider +String imageUri = "assets://image.png"; // from assets +String imageUri = "res://package name(any String or "")/" + R.drawable.ic_launcher +``` + ## UI Modules @@ -367,6 +435,8 @@ You can read the documents of [GreenDao](https://github.com/greenrobot/greenDAO) UltimateUI 项目分拆成widget,component,animations,lollipop 4个子项目,如果你只需要部分UI效果的话,你可以只依赖这些子项目.如果你想使用多个种类的UI项目的话,也可以简单的依赖UltimateAndroidUi项目(当然,你也可以依赖4个子项目)。 +将facebook/fresco集成入框架中,这提供了一种新的图片加载方案。此框架加载图片的效率更高,会自动处理包括显示占位图直到加载完成、下载图片、缓存图片、图片不再显示时,从内存中移除等等功能。 + [UI截图在这里](#demo_of_ui) [部分UI模块介绍](http://arccode.net/2015/02/03/UltimateAndroid-demo%E6%95%88%E6%9E%9C%E5%9B%BE%E6%96%87%E6%A1%A3-%E4%B8%80/)(感谢arccode) @@ -627,6 +697,72 @@ String imageUri = "drawable://" + R.drawable.image; // from drawables (only imag 可以查看Greendao的文档 :[GreenDao](https://github.com/greenrobot/greenDAO) +7.新的图片加载方案 + + 如果你已经使用或继承了CommonApplication,你可以如下使用: + +``` //圆形图片,并设置占位图 + FrescoHelper.load(Uri.parse(imageUrl)) + .placeholder(CommonUtil.getDrawable(R.drawable.ic_image3)) + .circle() + .into(simple_drawee_view);``` + + 或者高级使用: + + FrescoHelper.load(Uri.parse(imageUrl)) + .placeholder(CommonUtil.getDrawable(R.drawable.ic_image3)) + .circle() + .into(simple_drawee_view, new ControllerListener() { + @Override + public void onSubmit(String s, Object o) { + ... + } + @Override + public void onFinalImageSet(String s, Object o, Animatable animatable) { + ... + } + @Override + public void onIntermediateImageSet(String s, Object o) { + ... + } + @Override + public void onIntermediateImageFailed(String s, Throwable throwable) { + ... + } + @Override + public void onFailure(String s, Throwable throwable) { + ... + } + @Override + public void onRelease(String s) { + ... + } + }, new Postprocessor() { + @Override + public CloseableReference process(Bitmap bitmap, PlatformBitmapFactory platformBitmapFactory) { + return null; + } + @Override + public String getName() { + return null; + } + @Override + public CacheKey getPostprocessorCacheKey() { + return null; + } + }); + +可以使用的URI格式: + +``` java +String imageUri = "http://site.com/image.png"; // from Web +String imageUri = "https://static.pexels.com/photos/6789/flowers-petals-gift-flower-medium.jpg"; // from SSL Web +String imageUri = "file:///mnt/sdcard/image.png"; // from SD card +String imageUri = "content://media/external/audio/albumart/13"; // from content provider +String imageUri = "assets://image.png"; // from assets +String imageUri = "res://package name(any String or "")/" + R.drawable.ic_launcher +``` + ## UI 模块 diff --git a/UltimateAndroidGradle/app/build.gradle b/UltimateAndroidGradle/app/build.gradle index 622bec43..65f78605 100644 --- a/UltimateAndroidGradle/app/build.gradle +++ b/UltimateAndroidGradle/app/build.gradle @@ -10,6 +10,8 @@ android { targetSdkVersion 23 versionCode 1 versionName "1.0" + + multiDexEnabled true } buildTypes { release { diff --git a/UltimateAndroidGradle/demoofui/build.gradle b/UltimateAndroidGradle/demoofui/build.gradle index e318b8bd..de02879b 100644 --- a/UltimateAndroidGradle/demoofui/build.gradle +++ b/UltimateAndroidGradle/demoofui/build.gradle @@ -15,11 +15,13 @@ android { defaultConfig { applicationId "com.marshalchen.common.demoofui" minSdkVersion 14 - targetSdkVersion 22 + targetSdkVersion 23 versionCode 5 versionName "1.0.4" renderscriptTargetApi 22 renderscriptSupportModeEnabled true + + multiDexEnabled true } signingConfigs { @@ -83,5 +85,5 @@ dependencies { compile project(':ultimateandroiduilollipop') // compile 'com.marshalchen.ultimateandroid:ultimateandroidui:0.6.0' compile 'com.android.support:percent:23.1.0' - + compile 'com.android.support:multidex:1.0.1' } diff --git a/UltimateAndroidGradle/demoofui/src/main/java/com/marshalchen/common/demoofui/CommonApplication.java b/UltimateAndroidGradle/demoofui/src/main/java/com/marshalchen/common/demoofui/CommonApplication.java index 48029865..275781b6 100644 --- a/UltimateAndroidGradle/demoofui/src/main/java/com/marshalchen/common/demoofui/CommonApplication.java +++ b/UltimateAndroidGradle/demoofui/src/main/java/com/marshalchen/common/demoofui/CommonApplication.java @@ -1,6 +1,8 @@ package com.marshalchen.common.demoofui; import android.app.Application; +import android.support.multidex.MultiDexApplication; + import com.marshalchen.common.commonUtils.urlUtils.UniversalImageLoader; import com.marshalchen.common.uimodule.customFonts.CalligraphyConfig; import com.marshalchen.common.uimodule.passcodelock.AppLockManager; @@ -10,7 +12,7 @@ /** * Created by cym on 14-4-30. */ -public class CommonApplication extends Application { +public class CommonApplication extends MultiDexApplication { @Override public void onCreate() { super.onCreate(); diff --git a/UltimateAndroidGradle/gradle/wrapper/gradle-wrapper.properties b/UltimateAndroidGradle/gradle/wrapper/gradle-wrapper.properties index bcf6faaf..b4101d29 100644 --- a/UltimateAndroidGradle/gradle/wrapper/gradle-wrapper.properties +++ b/UltimateAndroidGradle/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sat Dec 13 21:22:23 CST 2014 +#Mon Oct 26 10:45:18 CST 2015 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.7-all.zip diff --git a/UltimateAndroidGradle/ultimateandroid/build.gradle b/UltimateAndroidGradle/ultimateandroid/build.gradle index dce7eede..d8e356b9 100644 --- a/UltimateAndroidGradle/ultimateandroid/build.gradle +++ b/UltimateAndroidGradle/ultimateandroid/build.gradle @@ -13,10 +13,12 @@ android { defaultConfig { // applicationId "com.marshalchen.common" - minSdkVersion 8 + minSdkVersion 9 targetSdkVersion 23 versionCode 1 versionName "1.0" + + multiDexEnabled true } buildTypes { release { @@ -46,7 +48,7 @@ dependencies { compile 'com.android.support:appcompat-v7:23.0.1' compile 'com.android.support:support-v4:23.0.1' compile 'com.android.support:recyclerview-v7:23.0.1' - + compile 'com.facebook.fresco:fresco:0.8.0' compile 'com.marshalchen.ultimaterecyclerview:library:0.3.6' compile 'com.loopj.android:android-async-http:1.4.9' compile 'com.nineoldandroids:library:2.4.0' diff --git a/UltimateAndroidGradle/ultimateandroid/src/main/java/com/marshalchen/common/CommonApplication.java b/UltimateAndroidGradle/ultimateandroid/src/main/java/com/marshalchen/common/CommonApplication.java index 516e8e83..1d6ab5d6 100644 --- a/UltimateAndroidGradle/ultimateandroid/src/main/java/com/marshalchen/common/CommonApplication.java +++ b/UltimateAndroidGradle/ultimateandroid/src/main/java/com/marshalchen/common/CommonApplication.java @@ -1,6 +1,9 @@ package com.marshalchen.common; import android.app.Application; + +import com.marshalchen.common.commonUtils.urlUtils.FrescoHelper; +import com.marshalchen.common.commonUtils.urlUtils.ImagePipelineConfigFactory; import com.marshalchen.common.commonUtils.urlUtils.UniversalImageLoader; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; @@ -16,6 +19,9 @@ public void onCreate() { // Create global configuration and initialize ImageLoader with this configuration ImageLoaderConfiguration config = UniversalImageLoader.getDefaultImageLoaderConfiguration(getApplicationContext()); ImageLoader.getInstance().init(config); + + // Initialize Fresco + FrescoHelper.init(getApplicationContext(), ImagePipelineConfigFactory.getImagePipelineConfig(getApplicationContext())); } @Override diff --git a/UltimateAndroidGradle/ultimateandroid/src/main/java/com/marshalchen/common/commonUtils/urlUtils/FrescoHelper.java b/UltimateAndroidGradle/ultimateandroid/src/main/java/com/marshalchen/common/commonUtils/urlUtils/FrescoHelper.java new file mode 100644 index 00000000..2e6207fe --- /dev/null +++ b/UltimateAndroidGradle/ultimateandroid/src/main/java/com/marshalchen/common/commonUtils/urlUtils/FrescoHelper.java @@ -0,0 +1,407 @@ +package com.marshalchen.common.commonUtils.urlUtils; + +import android.content.Context; +import android.graphics.PointF; +import android.graphics.drawable.Drawable; +import android.net.Uri; + +import com.facebook.common.util.UriUtil; +import com.facebook.drawee.backends.pipeline.Fresco; +import com.facebook.drawee.backends.pipeline.PipelineDraweeControllerBuilder; +import com.facebook.drawee.controller.ControllerListener; +import com.facebook.drawee.drawable.ScalingUtils; +import com.facebook.drawee.generic.GenericDraweeHierarchy; +import com.facebook.drawee.generic.RoundingParams; +import com.facebook.drawee.interfaces.DraweeController; +import com.facebook.drawee.view.SimpleDraweeView; +import com.facebook.imagepipeline.common.ResizeOptions; +import com.facebook.imagepipeline.core.ImagePipelineConfig; +import com.facebook.imagepipeline.request.ImageRequest; +import com.facebook.imagepipeline.request.ImageRequestBuilder; +import com.facebook.imagepipeline.request.Postprocessor; + +import java.io.File; + +/** + * Fresco support images show effect + */ +public class FrescoHelper { + Uri uri; + float sizeRatio = -1.0f; + ScalingUtils.ScaleType actualScaleType = ScalingUtils.ScaleType.CENTER_CROP; + PointF actualFocusPoint = null; + Drawable overlayDrawable = null; + Drawable placeholderDrawable = null; + int placeholderRes = 0; + RoundingParams roundingParams = null; + boolean autoPlayAnimations = false; + boolean tapToRetryEnabled = false; + boolean progressiveRenderingEnabled = false; + boolean localThumbnailPreviewsEnabled = false; + boolean autoRotateEnabled = false; + ResizeOptions resizeOptions = null; + + /** + * Initialize Fresco + */ + public static void init(Context context, ImagePipelineConfig config) { + Fresco.initialize(context, config); + } + + public FrescoHelper(Uri uri) { + if (uri == null) { + throw new IllegalArgumentException("uri == null"); + } + this.uri = uri; + } + + /** + * Laod image with URI + * @return + */ + public static FrescoHelper load(String path) { + return new FrescoHelper(Uri.parse(path)); + } + + public static FrescoHelper load(int resourceId) { + return new FrescoHelper(new Uri.Builder().scheme(UriUtil.LOCAL_RESOURCE_SCHEME).path(String.valueOf(resourceId)).build()); + } + + public static FrescoHelper load(File file) { + return new FrescoHelper(Uri.fromFile(file)); + } + + public static FrescoHelper load(Uri uri) { + return new FrescoHelper(uri); + } + + public FrescoHelper setSizeRatio(float ratio) { + this.sizeRatio = ratio; + return this; + } + + /** + * Set placeholderImage + * @return + */ + public FrescoHelper placeholder(int placeholderResId) { + this.placeholderRes = placeholderResId; + return this; + } + + public FrescoHelper placeholder(Drawable placeholderDrawable) { + this.placeholderDrawable = placeholderDrawable; + return this; + } + + /** + * Center without zooming + * @return + */ + public FrescoHelper center() { + return setScaleType(ScalingUtils.ScaleType.CENTER); + } + + /** + * Center with keep zooming and both sides is greater than or equal to show boundaries + * @return + */ + public FrescoHelper centerCrop() { + return setScaleType(ScalingUtils.ScaleType.CENTER_CROP); + } + + /** + * specified point with keep zooming and both sides is greater than or equal to show boundaries + * @return + */ + public FrescoHelper focusCrop(PointF point) { + setActualFocusPoint(point); + return setScaleType(ScalingUtils.ScaleType.FOCUS_CROP); + } + + public FrescoHelper setActualFocusPoint(PointF actualFocusPoint) { + this.actualFocusPoint = actualFocusPoint; + return this; + } + + /** + * Center with keep within the border + * @return + */ + public FrescoHelper centerInside() { + return setScaleType(ScalingUtils.ScaleType.CENTER_INSIDE); + } + + /** + * Center with keep zooming and fully displayed in the picture within the boundary + * @return + */ + public FrescoHelper fitCenter() { + return setScaleType(ScalingUtils.ScaleType.FIT_CENTER); + } + + // + /** + * Top left corner with keep zooming and fully displayed in the picture within the boundary + * @return + */ + public FrescoHelper fitStart() { + return setScaleType(ScalingUtils.ScaleType.FIT_START); + } + + /** + * Bottom right corner with keep zooming and fully displayed in the picture within the boundary + * @return + */ + public FrescoHelper fitEnd() { + return setScaleType(ScalingUtils.ScaleType.FIT_END); + } + + /** + * Do not save aspect ratio, fill the full display boundary + * @return + */ + public FrescoHelper fitXY() { + return setScaleType(ScalingUtils.ScaleType.FIT_XY); + } + + public FrescoHelper setScaleType(ScalingUtils.ScaleType actualScaleType) { + this.actualScaleType = actualScaleType; + return this; + } + + /** + * Circle image + * @return + */ + public FrescoHelper circle() { + return setRoundingParams(new RoundingParams().setRoundAsCircle(true)); + } + + /** + * Circle image with border + * @return + */ + public FrescoHelper circle(int borderWidth, int borderColor) { + return setRoundingParams(new RoundingParams().setRoundAsCircle(true).setBorder(borderColor, borderWidth)); + } + + /** + * The elliptical Settings + * @return + */ + public FrescoHelper roundedCorner(float radius) { + return roundedCorner(radius, radius, radius, radius); + } + + public FrescoHelper roundedCorner(float radius, int borderWidth, int borderColor) { + return roundedCorner(radius, radius, radius, radius, borderWidth, borderColor); + } + + public FrescoHelper roundedCorner(float topLeft, float topRight, float bottomRight, float bottomLeft) { + return setRoundingParams(new RoundingParams().setRoundAsCircle(false).setCornersRadii(topLeft, topRight, bottomRight, bottomLeft)); + } + + public FrescoHelper roundedCorner(float topLeft, float topRight, float bottomRight, float bottomLeft, int borderWidth, int borderColor) { + return setRoundingParams(new RoundingParams().setRoundAsCircle(false).setCornersRadii(topLeft, topRight, bottomRight, bottomLeft).setBorder(borderColor, borderWidth)); + } + + public FrescoHelper setRoundingParams(RoundingParams roundingParams) { + this.roundingParams = roundingParams; + return this; + } + + /** + * Set overlayImage + * @return + */ + public FrescoHelper overlay(Drawable overlayDrawable) { + this.overlayDrawable = overlayDrawable; + return this; + } + + /** + * Gif auto play + * @return + */ + public FrescoHelper autoPlayAnimations() { + this.autoPlayAnimations = true; + return this; + } + + /** + * Set click reload image if iamge request failure + * @return + */ + public FrescoHelper tapToRetryEnabled() { + this.tapToRetryEnabled = true; + return this; + } + + /** + * Set image progressiveRendering or not + * @return + */ + public FrescoHelper progressiveRenderingEnabled() { + this.progressiveRenderingEnabled = true; + return this; + } + + /** + * Thumbnail Preview. + * This feature support local URI only and iamge must be JPEG format + * @return + */ + public FrescoHelper localThumbnailPreviewsEnabled() { + this.localThumbnailPreviewsEnabled = true; + return this; + } + + /** + * Modify the image size before decode. + * This scaling method, bigger than Android built-in zoom range. + * Android camera pictures generated average size is very big, need to adjust the size to be displayed. + * At present, support only JPEG images but fortunately most of the Android camera is JPEG images. + * If you want to modify the image size, create ImageRequest, provide a ResizeOptions + * @return + */ + public FrescoHelper resizeOptions(int width, int height) { + this.resizeOptions = new ResizeOptions(width, height); + return this; + } + + /** + * Auto rotate + * @return + */ + public FrescoHelper autoRotateEnabled() { + this.autoRotateEnabled = true; + return this; + } + + public void into(SimpleDraweeView view, ControllerListener callback) { + into(view, callback, null); + } + + public void into(SimpleDraweeView view, Postprocessor postprocessor) { + into(view, null, postprocessor); + } + + public void into(SimpleDraweeView view) { + into(view, null, null); + } + + public void into(SimpleDraweeView view, ControllerListener callback, Postprocessor postprocessor) { + + GenericDraweeHierarchy hierarchy = view.getHierarchy(); + + boolean isHierarchyChange = false; + if (actualScaleType != ScalingUtils.ScaleType.CENTER_CROP) { + hierarchy.setActualImageScaleType(actualScaleType); + isHierarchyChange = true; + } + + if (actualFocusPoint != null) { + hierarchy.setActualImageFocusPoint(actualFocusPoint); + isHierarchyChange = true; + } + + if (overlayDrawable != null) { + hierarchy.setControllerOverlay(overlayDrawable); + isHierarchyChange = true; + } + + if (placeholderDrawable != null) { + hierarchy.setPlaceholderImage(placeholderDrawable); + isHierarchyChange = true; + } + + if (placeholderRes != 0) { + hierarchy.setPlaceholderImage(placeholderRes); + isHierarchyChange = true; + } + + if (roundingParams != null) { + hierarchy.setRoundingParams(roundingParams); + isHierarchyChange = true; + } + + ImageRequest request = null; + ImageRequestBuilder requestBuilder = ImageRequestBuilder.newBuilderWithSource(uri); + boolean isRequestChange = false; + if (autoRotateEnabled) { + requestBuilder.setAutoRotateEnabled(true); + isRequestChange = true; + } + + if (localThumbnailPreviewsEnabled) { + requestBuilder.setLocalThumbnailPreviewsEnabled(true); + isRequestChange = true; + } + + if (postprocessor != null) { + requestBuilder.setPostprocessor(postprocessor); + isRequestChange = true; + } + + if (progressiveRenderingEnabled) { + requestBuilder.setProgressiveRenderingEnabled(true); + isRequestChange = true; + } + + if (resizeOptions != null) { + requestBuilder.setResizeOptions(resizeOptions); + isRequestChange = true; + } + + if (isRequestChange) { + request = requestBuilder.build(); + } + + PipelineDraweeControllerBuilder controllerBuilder = Fresco.newDraweeControllerBuilder(); + DraweeController controller = null; + boolean isControllerChange = false; + if (callback != null) { + controllerBuilder.setControllerListener(callback); + isControllerChange = true; + } + + if (autoPlayAnimations) { + controllerBuilder.setAutoPlayAnimations(true); + isControllerChange = true; + } + + if (tapToRetryEnabled) { + controllerBuilder.setTapToRetryEnabled(true); + isControllerChange = true; + } + + if (request != null) { + controllerBuilder.setImageRequest(request); + isControllerChange = true; + } else if (request == null && isControllerChange) { + controllerBuilder.setUri(uri); + } + + if (isControllerChange) { + controllerBuilder.setOldController(view.getController()); + controller = controllerBuilder.build(); + } + + if (sizeRatio > 0) { + view.setAspectRatio(sizeRatio); + } + + if (isHierarchyChange) { + view.setHierarchy(hierarchy); + } + + if (controller != null) { + view.setController(controller); + } else { + view.setImageURI(uri); + } + + + } +} diff --git a/UltimateAndroidGradle/ultimateandroid/src/main/java/com/marshalchen/common/commonUtils/urlUtils/ImagePipelineConfigFactory.java b/UltimateAndroidGradle/ultimateandroid/src/main/java/com/marshalchen/common/commonUtils/urlUtils/ImagePipelineConfigFactory.java new file mode 100644 index 00000000..20394bbd --- /dev/null +++ b/UltimateAndroidGradle/ultimateandroid/src/main/java/com/marshalchen/common/commonUtils/urlUtils/ImagePipelineConfigFactory.java @@ -0,0 +1,83 @@ +package com.marshalchen.common.commonUtils.urlUtils; + +import android.content.Context; +import android.os.Build; +import android.os.Environment; + +import com.facebook.cache.disk.DiskCacheConfig; +import com.facebook.common.internal.Supplier; +import com.facebook.common.util.ByteConstants; +import com.facebook.imagepipeline.cache.MemoryCacheParams; +import com.facebook.imagepipeline.core.ImagePipelineConfig; + +import java.io.File; + +/** + * Get Config of ImagePipelineConfig + */ +public class ImagePipelineConfigFactory { + private static final String IMAGE_PIPELINE_CACHE_DIR = "imagepipeline_cache"; + + private static ImagePipelineConfig sImagePipelineConfig; + + private static final int MAX_HEAP_SIZE = (int) Runtime.getRuntime().maxMemory(); + + public static final int MAX_DISK_CACHE_SIZE = 300 * ByteConstants.MB; + public static final int MAX_MEMORY_CACHE_SIZE = MAX_HEAP_SIZE / 3; + + /** + * Creates config using android http stack as network backend. + */ + public static ImagePipelineConfig getImagePipelineConfig(Context context) { + if (sImagePipelineConfig == null) { + ImagePipelineConfig.Builder configBuilder = ImagePipelineConfig.newBuilder(context); + configureCaches(configBuilder, context); + sImagePipelineConfig = configBuilder.build(); + } + return sImagePipelineConfig; + } + + /** + * Configures disk and memory cache not to exceed common limits + */ + private static void configureCaches(ImagePipelineConfig.Builder configBuilder, Context context) { + final MemoryCacheParams bitmapCacheParams = new MemoryCacheParams( + MAX_MEMORY_CACHE_SIZE, // Max total size of elements in the cache + Integer.MAX_VALUE, // Max entries in the cache + MAX_MEMORY_CACHE_SIZE, // Max total size of elements in eviction queue + Integer.MAX_VALUE, // Max length of eviction queue + Integer.MAX_VALUE); // Max cache entry size + configBuilder.setBitmapMemoryCacheParamsSupplier( + new Supplier() { + public MemoryCacheParams get() { + return bitmapCacheParams; + } + }) + .setMainDiskCacheConfig(DiskCacheConfig.newBuilder() + .setBaseDirectoryPath(getExternalCacheDir(context)) + .setBaseDirectoryName(IMAGE_PIPELINE_CACHE_DIR) + .setMaxCacheSize(MAX_DISK_CACHE_SIZE) + .build()); + } + + public static File getExternalCacheDir(final Context context) { + if (hasExternalCacheDir()) + return context.getExternalCacheDir(); + + // Before Froyo we need to construct the external cache dir ourselves + final String cacheDir = "/Android/data/" + context.getPackageName() + "/cache/"; + return createFile(Environment.getExternalStorageDirectory().getPath() + cacheDir, ""); + } + + public static boolean hasExternalCacheDir() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO; + } + + public static File createFile(String folderPath, String fileName) { + File destDir = new File(folderPath); + if (!destDir.exists()) { + destDir.mkdirs(); + } + return new File(folderPath, fileName); + } +} diff --git a/UltimateAndroidGradle/ultimateandroidui/build.gradle b/UltimateAndroidGradle/ultimateandroidui/build.gradle index 328e9f1a..e2e43c79 100644 --- a/UltimateAndroidGradle/ultimateandroidui/build.gradle +++ b/UltimateAndroidGradle/ultimateandroidui/build.gradle @@ -19,6 +19,8 @@ android { targetSdkVersion 23 versionCode 1 versionName "1.0" + + multiDexEnabled true } buildTypes { release { diff --git a/UltimateAndroidGradle/ultimateandroiduianimation/build.gradle b/UltimateAndroidGradle/ultimateandroiduianimation/build.gradle index 6c81c298..0049a175 100644 --- a/UltimateAndroidGradle/ultimateandroiduianimation/build.gradle +++ b/UltimateAndroidGradle/ultimateandroiduianimation/build.gradle @@ -9,6 +9,8 @@ android { targetSdkVersion 23 versionCode 1 versionName "1.0" + + multiDexEnabled true } buildTypes { release { diff --git a/UltimateAndroidGradle/ultimateandroiduicomponent/build.gradle b/UltimateAndroidGradle/ultimateandroiduicomponent/build.gradle index c62bdb40..fef6a339 100644 --- a/UltimateAndroidGradle/ultimateandroiduicomponent/build.gradle +++ b/UltimateAndroidGradle/ultimateandroiduicomponent/build.gradle @@ -9,6 +9,8 @@ android { targetSdkVersion 23 versionCode 1 versionName "1.0" + + multiDexEnabled true } buildTypes { release { diff --git a/UltimateAndroidGradle/ultimateandroiduilollipop/build.gradle b/UltimateAndroidGradle/ultimateandroiduilollipop/build.gradle index b65e1a71..e27dd30c 100644 --- a/UltimateAndroidGradle/ultimateandroiduilollipop/build.gradle +++ b/UltimateAndroidGradle/ultimateandroiduilollipop/build.gradle @@ -9,6 +9,8 @@ android { targetSdkVersion 23 versionCode 1 versionName "1.0" + + multiDexEnabled true } buildTypes { release { diff --git a/UltimateAndroidGradle/ultimateandroiduiwidget/build.gradle b/UltimateAndroidGradle/ultimateandroiduiwidget/build.gradle index fa3e331b..60580b4b 100644 --- a/UltimateAndroidGradle/ultimateandroiduiwidget/build.gradle +++ b/UltimateAndroidGradle/ultimateandroiduiwidget/build.gradle @@ -9,6 +9,8 @@ android { targetSdkVersion 23 versionCode 1 versionName "1.0" + + multiDexEnabled true } buildTypes { release {