arg, String argName) {
109 | if (arg == null || arg.size() < 1) {
110 | throw new IllegalArgumentException("argument is null: " + argName);
111 | }
112 | }
113 |
114 | /**
115 | * Safe parse the given string to long value.
116 | */
117 | public static long parseLong(String value, long defaultValue) {
118 | if (!TextUtils.isEmpty(value)) {
119 | try {
120 | return Integer.parseInt(value);
121 | } catch (Exception ignored) {
122 | }
123 | }
124 | return defaultValue;
125 | }
126 |
127 | /**
128 | * combine two path into a single path with File.separator.
129 | * Handle all cases where the separator already exists.
130 | */
131 | public static String pathCombine(String path1, String path2) {
132 | if (path2 == null)
133 | return path1;
134 | else if (path1 == null)
135 | return path2;
136 |
137 | path1 = path1.trim();
138 | path2 = path2.trim();
139 | if (path1.endsWith(File.separator)) {
140 | if (path2.startsWith(File.separator))
141 | return path1 + path2.substring(1);
142 | else
143 | return path1 + path2;
144 | } else {
145 | if (path2.startsWith(File.separator))
146 | return path1 + path2;
147 | else
148 | return path1 + File.separator + path2;
149 | }
150 | }
151 |
152 | /**
153 | * Close the given closeable object (Stream) in a safe way: check if it is null and catch-log
154 | * exception thrown.
155 | *
156 | * @param closeable the closable object to close
157 | */
158 | public static void closeSafe(Closeable closeable) {
159 | if (closeable != null) {
160 | try {
161 | closeable.close();
162 | } catch (IOException e) {
163 | FILLogger.warn("Failed to close closable object [{}]", e, closeable);
164 | }
165 | }
166 | }
167 |
168 | /**
169 | * Delete the given file in a safe way: check if it is null and catch-log exception thrown.
170 | *
171 | * @param file the file to delete
172 | */
173 | public static void deleteSafe(File file) {
174 | if (file != null) {
175 | try {
176 | //noinspection ResultOfMethodCallIgnored
177 | file.delete();
178 | } catch (Throwable e) {
179 | FILLogger.warn("Failed to delete file [{}]", e, file);
180 | }
181 | }
182 | }
183 |
184 | /**
185 | * Format the given format string by replacing {} placeholders with given arguments.
186 | */
187 | public static String format(String format, Object arg1) {
188 | return replacePlaceHolder(format, arg1);
189 | }
190 |
191 | /**
192 | * Format the given format string by replacing {} placeholders with given arguments.
193 | */
194 | public static String format(String format, Object arg1, Object arg2) {
195 | format = replacePlaceHolder(format, arg1);
196 | return replacePlaceHolder(format, arg2);
197 | }
198 |
199 | /**
200 | * Format the given format string by replacing {} placeholders with given arguments.
201 | */
202 | public static String format(String format, Object arg1, Object arg2, Object arg3) {
203 | format = replacePlaceHolder(format, arg1);
204 | format = replacePlaceHolder(format, arg2);
205 | return replacePlaceHolder(format, arg3);
206 | }
207 |
208 | /**
209 | * Format the given format string by replacing {} placeholders with given arguments.
210 | */
211 | public static String format(String format, Object arg1, Object arg2, Object arg3, Object arg4) {
212 | format = replacePlaceHolder(format, arg1);
213 | format = replacePlaceHolder(format, arg2);
214 | format = replacePlaceHolder(format, arg3);
215 | return replacePlaceHolder(format, arg4);
216 | }
217 |
218 | /**
219 | * Format the given format string by replacing {} placeholders with given arguments.
220 | */
221 | public static String format(String format, Object... args) {
222 | for (Object arg : args) {
223 | format = replacePlaceHolder(format, arg);
224 | }
225 | return format;
226 | }
227 |
228 | /**
229 | * Replace the first occurrence of {} placeholder in format string by arg1 toString() value.
230 | */
231 | private static String replacePlaceHolder(String format, Object arg1) {
232 | int idx = format.indexOf("{}");
233 | if (idx > -1) {
234 | format = format.substring(0, idx) + arg1 + format.substring(idx + 2);
235 | }
236 | return format;
237 | }
238 |
239 | public static ThreadFactory threadFactory(final String name, final boolean daemon) {
240 | return new ThreadFactory() {
241 | @Override
242 | public Thread newThread(Runnable runnable) {
243 | Thread result = new Thread(runnable, name);
244 | result.setDaemon(daemon);
245 | return result;
246 | }
247 | };
248 | }
249 |
250 | }
--------------------------------------------------------------------------------
/fastimageloader/src/main/java/com/theartofdev/fastimageloader/target/AnimatingTargetDrawable.java:
--------------------------------------------------------------------------------
1 | // "Therefore those skilled at the unorthodox
2 | // are infinite as heaven and earth,
3 | // inexhaustible as the great rivers.
4 | // When they come to an end,
5 | // they begin again,
6 | // like the days and months;
7 | // they die and are reborn,
8 | // like the four seasons."
9 | //
10 | // - Sun Tsu,
11 | // "The Art of War"
12 |
13 | package com.theartofdev.fastimageloader.target;
14 |
15 | /**
16 | * Used to declare target drawable to support animation.
17 | */
18 | public interface AnimatingTargetDrawable {
19 |
20 | /**
21 | * Is the drawable is currently animating fade-in of the image
22 | */
23 | boolean isAnimating();
24 | }
--------------------------------------------------------------------------------
/fastimageloader/src/main/java/com/theartofdev/fastimageloader/target/TargetAvatarImageView.java:
--------------------------------------------------------------------------------
1 | // "Therefore those skilled at the unorthodox
2 | // are infinite as heaven and earth,
3 | // inexhaustible as the great rivers.
4 | // When they come to an end,
5 | // they begin again,
6 | // like the days and months;
7 | // they die and are reborn,
8 | // like the four seasons."
9 | //
10 | // - Sun Tsu,
11 | // "The Art of War"
12 |
13 | package com.theartofdev.fastimageloader.target;
14 |
15 | import android.content.Context;
16 | import android.graphics.Canvas;
17 | import android.graphics.Color;
18 | import android.graphics.Paint;
19 | import android.text.TextUtils;
20 | import android.util.AttributeSet;
21 |
22 | import com.theartofdev.fastimageloader.LoadState;
23 | import com.theartofdev.fastimageloader.impl.util.FILUtils;
24 |
25 | /**
26 | * TODO:a add doc
27 | */
28 | public class TargetAvatarImageView extends TargetImageView {
29 |
30 | //region: Fields and Consts
31 |
32 | /**
33 | * Full AuthorName
34 | */
35 | protected String mName;
36 |
37 | /**
38 | * Acronyms, 2 letters will be written as placeholder
39 | */
40 | protected String mAcronyms;
41 |
42 | /**
43 | * Calculate background color, by 'AuthorName' hasecode % 30
44 | */
45 | protected static Paint mBackPaint;
46 |
47 | /**
48 | * WHITE color painter for text
49 | */
50 | protected static Paint mTextPaint;
51 | //endregion
52 |
53 | public TargetAvatarImageView(Context context) {
54 | super(context);
55 | setRounded(true);
56 | }
57 |
58 | public TargetAvatarImageView(Context context, AttributeSet attrs) {
59 | super(context, attrs);
60 | setRounded(true);
61 | }
62 |
63 | public TargetAvatarImageView(Context context, AttributeSet attrs, int defStyle) {
64 | super(context, attrs, defStyle);
65 | setRounded(true);
66 | }
67 |
68 | /**
69 | * See: {@link #loadAvatar(String, String, String, String)}
70 | */
71 | public void loadAvatar(String source, String name, String specKey) {
72 | loadAvatar(source, name, specKey, null);
73 | }
74 |
75 | /**
76 | * Load avatar image from the given source, use the given name for placeholder while loading
77 | * or avatar load failed.
78 | *
79 | * @param source the avatar source URL to load from
80 | * @param name the user name to use while avatar is loading or failed
81 | * @param specKey the spec to load the image by
82 | * @param altSpecKey optional: the spec to use for memory cached image in case the primary is not found.
83 | */
84 | public void loadAvatar(String source, String name, String specKey, String altSpecKey) {
85 | if (!TextUtils.equals(mName, name)) {
86 | mName = TextUtils.isEmpty(name) ? "UU" : name;
87 | mAcronyms = null;
88 | }
89 | loadImage(source, specKey, altSpecKey, false);
90 | }
91 |
92 | //region: Private methods
93 |
94 | @Override
95 | protected void drawPlaceholder(Canvas canvas, LoadState loadState) {
96 | if (!TextUtils.isEmpty(mName)) {
97 | if (mAcronyms == null) {
98 | init();
99 | }
100 |
101 | FILUtils.rectF.set(getPaddingLeft(), getPaddingTop(), getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
102 | if (isRounded()) {
103 | canvas.drawRoundRect(FILUtils.rectF, getWidth(), getHeight(), mBackPaint);
104 | } else {
105 | canvas.drawRect(FILUtils.rectF, mBackPaint);
106 | }
107 |
108 | mTextPaint.setTextSize(getWidth() / 1.8f);
109 | int xPos = canvas.getWidth() / 2;
110 | int yPos = (int) ((canvas.getHeight() / 2) - ((mTextPaint.descent() + mTextPaint.ascent()) / 2));
111 | canvas.drawText(mAcronyms, xPos, yPos, mTextPaint);
112 | }
113 | }
114 |
115 | /**
116 | * Init the user acronym and the paint object required.
117 | */
118 | protected void init() {
119 | if (mBackPaint == null) {
120 | mBackPaint = new Paint();
121 | mBackPaint.setColor(Color.LTGRAY);
122 | mBackPaint.setAntiAlias(true);
123 | }
124 |
125 | if (mTextPaint == null) {
126 | mTextPaint = new Paint();
127 | mTextPaint.setColor(Color.DKGRAY);
128 | mTextPaint.setTextAlign(Paint.Align.CENTER);
129 | }
130 |
131 | int idx = mName.indexOf(' ');
132 | if (idx < 0) {
133 | idx = 0;
134 | while (idx + 1 < mName.length() && Character.isLowerCase(mName.charAt(idx + 1))) {
135 | idx++;
136 | }
137 | }
138 | mAcronyms = idx > -1 && idx + 1 < mName.length()
139 | ? String.format("%c%c", mName.charAt(0), mName.charAt(idx + 1))
140 | : mName.substring(0, 1);
141 | }
142 | //endregion
143 | }
--------------------------------------------------------------------------------
/fastimageloader/src/main/java/com/theartofdev/fastimageloader/target/TargetCircleDrawable.java:
--------------------------------------------------------------------------------
1 | // "Therefore those skilled at the unorthodox
2 | // are infinite as heaven and earth,
3 | // inexhaustible as the great rivers.
4 | // When they come to an end,
5 | // they begin again,
6 | // like the days and months;
7 | // they die and are reborn,
8 | // like the four seasons."
9 | //
10 | // - Sun Tsu,
11 | // "The Art of War"
12 |
13 | package com.theartofdev.fastimageloader.target;
14 |
15 | import android.graphics.Bitmap;
16 | import android.graphics.BitmapShader;
17 | import android.graphics.Canvas;
18 | import android.graphics.ColorFilter;
19 | import android.graphics.Matrix;
20 | import android.graphics.Paint;
21 | import android.graphics.Rect;
22 | import android.graphics.Shader;
23 | import android.graphics.drawable.Drawable;
24 | import android.os.SystemClock;
25 |
26 | import com.theartofdev.fastimageloader.LoadedFrom;
27 | import com.theartofdev.fastimageloader.impl.util.FILUtils;
28 |
29 | /**
30 | * Drawable used for loaded images with additional capabilities:
31 | * 1. scale the image to the set rectangle.
32 | * 2. render round image
33 | * 3. fade effect for showing the image at start.
34 | * 4. showing indicator if the image was loading from memory/disk/network.
35 | */
36 | public class TargetCircleDrawable extends Drawable implements AnimatingTargetDrawable {
37 |
38 | //region: Fields and Consts
39 |
40 | private static final float FADE_DURATION = 200f;
41 |
42 | protected final Paint mPaint;
43 |
44 | protected final Matrix mMatrix = new Matrix();
45 |
46 | protected final LoadedFrom mLoadedFrom;
47 |
48 | protected final float mBitmapWidth;
49 |
50 | protected final float mBitmapHeight;
51 |
52 | protected float mScale = -1;
53 |
54 | protected int mTranslateX = -1;
55 |
56 | protected int mTranslateY = -1;
57 |
58 | /**
59 | * used for fade animation progress
60 | */
61 | protected long mStartTimeMillis;
62 | //endregion
63 |
64 | /**
65 | * @param bitmap the bitmap to render in the drawable
66 | * @param loadedFrom where the bitmap was loaded from MEMORY/DISK/NETWORK for debug indicator
67 | * @param showFade if to show fade effect starting from now
68 | */
69 | public TargetCircleDrawable(Bitmap bitmap, LoadedFrom loadedFrom, boolean showFade) {
70 | FILUtils.notNull(bitmap, "bitmap");
71 |
72 | mLoadedFrom = loadedFrom;
73 |
74 | mBitmapWidth = bitmap.getWidth();
75 | mBitmapHeight = bitmap.getHeight();
76 |
77 | mPaint = new Paint();
78 | mPaint.setAntiAlias(true);
79 | mPaint.setShader(new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
80 |
81 | mStartTimeMillis = showFade ? SystemClock.uptimeMillis() : 0;
82 | }
83 |
84 | @Override
85 | public boolean isAnimating() {
86 | return mStartTimeMillis > 0;
87 | }
88 |
89 | @Override
90 | public void setAlpha(int alpha) {
91 |
92 | }
93 |
94 | @Override
95 | public void setColorFilter(ColorFilter cf) {
96 |
97 | }
98 |
99 | @Override
100 | public int getOpacity() {
101 | return 0;
102 | }
103 |
104 | /**
105 | * {@inheritDoc}
106 | *
107 | * On set of bounds update the transform matrix applied on the bitmap to fit into the bounds.
108 | * - Scale to fit the dimensions of the image into the bounded rectangle.
109 | * - Offset the rendered bitmap to center the dimension that is larger\smaller than the bounds.
110 | *
111 | */
112 | @Override
113 | public void setBounds(int left, int top, int right, int bottom) {
114 | super.setBounds(left, top, right, bottom);
115 | float scale = Math.max((right - left) / mBitmapWidth, (bottom - top) / mBitmapHeight);
116 | int translateX = (int) (((right - left) - mBitmapWidth * scale) / 2);
117 | int translateY = (int) (((bottom - top) - mBitmapHeight * scale) / 2);
118 |
119 | if (Math.abs(scale - mScale) > 0.01 || translateX != mTranslateX || translateY != mTranslateY) {
120 | mScale = scale;
121 | mTranslateX = translateX;
122 | mTranslateY = translateY;
123 | if (mScale != 0 || mTranslateX != 0 || mTranslateY != 0) {
124 | if (mScale != 0)
125 | mMatrix.setScale(mScale, mScale);
126 | if (mTranslateX != 0 || mTranslateY != 0)
127 | mMatrix.postTranslate(mTranslateX, mTranslateY);
128 | mPaint.getShader().setLocalMatrix(mMatrix);
129 | } else {
130 | mPaint.getShader().setLocalMatrix(null);
131 | }
132 | }
133 | }
134 |
135 | /**
136 | * {@inheritDoc}
137 | *
138 | * Additional functionality:
139 | * Draw bitmap with opacity to show fade-in if animating.
140 | * Draw loaded from debug indicator.
141 | *
142 | */
143 | @Override
144 | public void draw(Canvas canvas) {
145 | float normalized = (SystemClock.uptimeMillis() - mStartTimeMillis) / FADE_DURATION;
146 | if (normalized >= 1f) {
147 | drawBitmap(canvas);
148 | if (mStartTimeMillis > 0)
149 | invalidateSelf();
150 | mStartTimeMillis = 0;
151 | } else {
152 | mPaint.setAlpha((int) (255 * normalized));
153 | drawBitmap(canvas);
154 | mPaint.setAlpha(255);
155 | invalidateSelf();
156 | }
157 |
158 | if (TargetHelper.debugIndicator) {
159 | Rect bounds = getBounds();
160 | TargetHelper.drawDebugIndicator(canvas, mLoadedFrom, bounds.width(), bounds.height());
161 | }
162 | }
163 |
164 | /**
165 | * Draw the bitmap on the canvas either rounded or rectangular.
166 | */
167 | protected void drawBitmap(Canvas canvas) {
168 | Rect bounds = getBounds();
169 | FILUtils.rectF.set(0, 0, bounds.width(), bounds.height());
170 | canvas.drawRoundRect(FILUtils.rectF, bounds.width() / 2, bounds.height() / 2, mPaint);
171 | }
172 | }
--------------------------------------------------------------------------------
/fastimageloader/src/main/java/com/theartofdev/fastimageloader/target/TargetDrawable.java:
--------------------------------------------------------------------------------
1 | // "Therefore those skilled at the unorthodox
2 | // are infinite as heaven and earth,
3 | // inexhaustible as the great rivers.
4 | // When they come to an end,
5 | // they begin again,
6 | // like the days and months;
7 | // they die and are reborn,
8 | // like the four seasons."
9 | //
10 | // - Sun Tsu,
11 | // "The Art of War"
12 |
13 | package com.theartofdev.fastimageloader.target;
14 |
15 | import android.graphics.Bitmap;
16 | import android.graphics.Canvas;
17 | import android.graphics.Rect;
18 | import android.graphics.drawable.BitmapDrawable;
19 | import android.os.SystemClock;
20 |
21 | import com.theartofdev.fastimageloader.LoadedFrom;
22 | import com.theartofdev.fastimageloader.impl.util.FILUtils;
23 |
24 | /**
25 | * Drawable used for loaded images with additional capabilities:
26 | * 1. fade effect for showing the image at start.
27 | * 2. showing indicator if the image was loading from memory/disk/network.
28 | */
29 | public class TargetDrawable extends BitmapDrawable implements AnimatingTargetDrawable {
30 |
31 | //region: Fields and Consts
32 |
33 | private static final float FADE_DURATION = 200f;
34 |
35 | protected final LoadedFrom mLoadedFrom;
36 |
37 | /**
38 | * used for fade animation progress
39 | */
40 | protected long mStartTimeMillis;
41 | //endregion
42 |
43 | /**
44 | * @param bitmap the bitmap to render in the drawable
45 | * @param loadedFrom where the bitmap was loaded from MEMORY/DISK/NETWORK for debug indicator
46 | * @param showFade if to show fade effect starting from now
47 | */
48 | public TargetDrawable(Bitmap bitmap, LoadedFrom loadedFrom, boolean showFade) {
49 | super(bitmap);
50 | FILUtils.notNull(bitmap, "bitmap");
51 |
52 | mLoadedFrom = loadedFrom;
53 |
54 | mStartTimeMillis = showFade ? SystemClock.uptimeMillis() : 0;
55 | }
56 |
57 | @Override
58 | public boolean isAnimating() {
59 | return mStartTimeMillis > 0;
60 | }
61 |
62 | /**
63 | * {@inheritDoc}
64 | *
65 | * Additional functionality:
66 | * Draw bitmap with opacity to show fade-in if animating.
67 | * Draw loaded from debug indicator.
68 | *
69 | */
70 | @Override
71 | public void draw(Canvas canvas) {
72 | float normalized = (SystemClock.uptimeMillis() - mStartTimeMillis) / FADE_DURATION;
73 | if (normalized >= 1f) {
74 | super.draw(canvas);
75 | if (mStartTimeMillis > 0)
76 | invalidateSelf();
77 | mStartTimeMillis = 0;
78 | } else {
79 | setAlpha((int) (255 * normalized));
80 | super.draw(canvas);
81 | setAlpha(255);
82 | invalidateSelf();
83 | }
84 |
85 | if (TargetHelper.debugIndicator) {
86 | Rect bounds = getBounds();
87 | TargetHelper.drawDebugIndicator(canvas, mLoadedFrom, bounds.width(), bounds.height());
88 | }
89 | }
90 |
91 | //region: Inner class: Animated
92 |
93 | //endregion
94 | }
--------------------------------------------------------------------------------
/fastimageloader/src/main/java/com/theartofdev/fastimageloader/target/TargetHelper.java:
--------------------------------------------------------------------------------
1 | // "Therefore those skilled at the unorthodox
2 | // are infinite as heaven and earth,
3 | // inexhaustible as the great rivers.
4 | // When they come to an end,
5 | // they begin again,
6 | // like the days and months;
7 | // they die and are reborn,
8 | // like the four seasons."
9 | //
10 | // - Sun Tsu,
11 | // "The Art of War"
12 |
13 | package com.theartofdev.fastimageloader.target;
14 |
15 | import android.graphics.Canvas;
16 | import android.graphics.Color;
17 | import android.graphics.Paint;
18 | import android.graphics.RectF;
19 |
20 | import com.theartofdev.fastimageloader.LoadedFrom;
21 |
22 | import static android.graphics.Color.GREEN;
23 | import static android.graphics.Color.RED;
24 | import static android.graphics.Color.WHITE;
25 | import static android.graphics.Color.YELLOW;
26 |
27 | /**
28 | * Helper methods for Target Drawable or Image View code.
29 | */
30 | public final class TargetHelper {
31 |
32 | /**
33 | * Used to paint debug indicator
34 | */
35 | private static Paint mDebugPaint;
36 |
37 | /**
38 | * Paint used to draw download progress
39 | */
40 | private static Paint mProgressPaint;
41 |
42 | /**
43 | * If to show indicator if the image was loaded from MEMORY/DISK/NETWORK.
44 | */
45 | public static boolean debugIndicator;
46 |
47 | /**
48 | * The density of the current
49 | */
50 | public static float mDensity;
51 |
52 | private TargetHelper() {
53 | }
54 |
55 | /**
56 | * draw indicator on where the image was loaded from.
57 | * Green - memory, Yellow - disk, Red - network.
58 | */
59 | public static void drawDebugIndicator(Canvas canvas, LoadedFrom loadedFrom, int width, int height) {
60 | if (debugIndicator) {
61 | if (mDebugPaint == null) {
62 | mDebugPaint = new Paint();
63 | mDebugPaint.setAntiAlias(true);
64 | }
65 |
66 | mDebugPaint.setColor(WHITE);
67 | canvas.drawCircle(width / 2, height / 2, 6 * mDensity, mDebugPaint);
68 |
69 | mDebugPaint.setColor(loadedFrom == LoadedFrom.MEMORY ? GREEN : loadedFrom == LoadedFrom.DISK ? YELLOW : RED);
70 | canvas.drawCircle(width / 2, height / 2, 4 * mDensity, mDebugPaint);
71 | }
72 | }
73 |
74 | /**
75 | * Draw indicator of download progress.
76 | *
77 | * @param downloaded downloaded bytes
78 | * @param contentLength total bytes
79 | */
80 | public static void drawProgressIndicator(Canvas canvas, long downloaded, long contentLength) {
81 | if (contentLength > 0 && downloaded < contentLength) {
82 | if (mProgressPaint == null) {
83 | mProgressPaint = new Paint();
84 | mProgressPaint.setAntiAlias(true);
85 | mProgressPaint.setColor(Color.argb(160, 0, 160, 0));
86 | }
87 |
88 | float s = (float) Math.min(36 * mDensity, Math.min(canvas.getWidth() * .2, canvas.getHeight() * .2));
89 | int l = canvas.getWidth() / 2;
90 | int t = canvas.getHeight() / 2;
91 | RectF rect = new RectF(l - s / 2, t - s / 2, l + s / 2, t + s / 2);
92 | canvas.drawArc(rect, -90, 360f * downloaded / contentLength, true, mProgressPaint);
93 | }
94 | }
95 | }
96 |
97 |
--------------------------------------------------------------------------------
/fastimageloader/src/main/java/com/theartofdev/fastimageloader/target/TargetImageView.java:
--------------------------------------------------------------------------------
1 | // "Therefore those skilled at the unorthodox
2 | // are infinite as heaven and earth,
3 | // inexhaustible as the great rivers.
4 | // When they come to an end,
5 | // they begin again,
6 | // like the days and months;
7 | // they die and are reborn,
8 | // like the four seasons."
9 | //
10 | // - Sun Tsu,
11 | // "The Art of War"
12 |
13 | package com.theartofdev.fastimageloader.target;
14 |
15 | import android.content.Context;
16 | import android.graphics.Canvas;
17 | import android.graphics.drawable.Drawable;
18 | import android.util.AttributeSet;
19 | import android.widget.ImageView;
20 |
21 | import com.theartofdev.fastimageloader.LoadState;
22 | import com.theartofdev.fastimageloader.impl.util.FILUtils;
23 |
24 | /**
25 | * {@link ImageView} with embedded handling of loading image using {@link com.theartofdev.fastimageloader.FastImageLoader}
26 | * and managing its lifecycle.
27 | */
28 | public class TargetImageView extends ImageView {
29 |
30 | //region: Fields and Consts
31 |
32 | /**
33 | * The target image handler to load the image and control its lifecycle.
34 | */
35 | protected TargetImageViewHandler mHandler;
36 |
37 | /**
38 | * The placeholder drawable to draw while the image is not loaded
39 | */
40 | protected Drawable mPlaceholder;
41 | //endregion
42 |
43 | public TargetImageView(Context context) {
44 | super(context);
45 | mHandler = new TargetImageViewHandler(this);
46 | mHandler.setInvalidateOnDownloading(true);
47 | }
48 |
49 | public TargetImageView(Context context, AttributeSet attrs) {
50 | super(context, attrs);
51 | mHandler = new TargetImageViewHandler(this);
52 | mHandler.setInvalidateOnDownloading(true);
53 | }
54 |
55 | public TargetImageView(Context context, AttributeSet attrs, int defStyle) {
56 | super(context, attrs, defStyle);
57 | mHandler = new TargetImageViewHandler(this);
58 | mHandler.setInvalidateOnDownloading(true);
59 | }
60 |
61 | /**
62 | * The URL source of the image
63 | */
64 | public String getUrl() {
65 | return mHandler.getUri();
66 | }
67 |
68 | /**
69 | * the spec to load the image by
70 | */
71 | public String getSpecKey() {
72 | return mHandler.getSpecKey();
73 | }
74 |
75 | /**
76 | * Is the image should be rendered rounded
77 | */
78 | public boolean isRounded() {
79 | return mHandler.isRounded();
80 | }
81 |
82 | /**
83 | * Is the image should be rendered rounded
84 | */
85 | public void setRounded(boolean isRounded) {
86 | mHandler.setRounded(isRounded);
87 | }
88 |
89 | /**
90 | * If to show download progress indicator when the requested image is downloading.
91 | */
92 | public boolean isShowDownloadProgressIndicator() {
93 | return mHandler.isInvalidateOnDownloading();
94 | }
95 |
96 | /**
97 | * If to show download progress indicator when the requested image is downloading.
98 | */
99 | public void setShowDownloadProgressIndicator(boolean show) {
100 | mHandler.setInvalidateOnDownloading(show);
101 | }
102 |
103 | /**
104 | * The placeholder drawable to draw while the image is not loaded
105 | */
106 | public Drawable getPlaceholder() {
107 | return mPlaceholder;
108 | }
109 |
110 | /**
111 | * The placeholder drawable to draw while the image is not loaded
112 | */
113 | public void setPlaceholder(Drawable placeholder) {
114 | mPlaceholder = placeholder;
115 | }
116 |
117 | @Override
118 | public void setImageDrawable(Drawable drawable) {
119 | super.setImageDrawable(drawable);
120 | if (drawable == null) {
121 | mHandler.clearUsedBitmap();
122 | }
123 | }
124 |
125 | /**
126 | * See: {@link #loadImage(String, String, String, boolean)}.
127 | */
128 | public void loadImage(String url, String specKey) {
129 | mHandler.loadImage(url, specKey, null, false);
130 | }
131 |
132 | /**
133 | * See: {@link #loadImage(String, String, String, boolean)}.
134 | */
135 | public void loadImage(String url, String specKey, String altSpecKey) {
136 | mHandler.loadImage(url, specKey, altSpecKey, false);
137 | }
138 |
139 | /**
140 | * Load image from the given source.
141 | *
142 | * @param url the avatar source URL to load from
143 | * @param specKey the spec to load the image by
144 | * @param altSpecKey optional: the spec to use for memory cached image in case the primary is not found.
145 | * @param force true - force image load even if it is the same source
146 | */
147 | public void loadImage(String url, String specKey, String altSpecKey, boolean force) {
148 | mHandler.loadImage(url, specKey, altSpecKey, force);
149 | }
150 |
151 | /**
152 | * On image view visibility change set show/hide on the image handler to it will update its in-use status.
153 | */
154 | @Override
155 | protected void onWindowVisibilityChanged(int visibility) {
156 | super.onWindowVisibilityChanged(visibility);
157 | mHandler.onViewVisibilityChanged(visibility);
158 | }
159 |
160 | /**
161 | * Override draw to draw placeholder before the image if it is not loaded yet or animating fade-in.
162 | */
163 | @Override
164 | public void onDraw(@SuppressWarnings("NullableProblems") Canvas canvas) {
165 | if (getDrawable() == null || mHandler.isAnimating()) {
166 | drawPlaceholder(canvas, mHandler.getLoadState());
167 | }
168 |
169 | super.onDraw(canvas);
170 |
171 | if (isShowDownloadProgressIndicator() && mHandler.getContentLength() > 0 && mHandler.getDownloaded() < mHandler.getContentLength()) {
172 | drawProgressIndicator(canvas);
173 | }
174 | }
175 |
176 | /**
177 | * Draw placeholder if the image is loading/animating to show or failed to load.
178 | *
179 | * @param loadState the current load state of the image to draw specific placeholder
180 | */
181 | protected void drawPlaceholder(Canvas canvas, LoadState loadState) {
182 | if (mPlaceholder != null) {
183 | canvas.getClipBounds(FILUtils.rect);
184 | mPlaceholder.setBounds(FILUtils.rect);
185 | mPlaceholder.draw(canvas);
186 | }
187 | }
188 |
189 | /**
190 | * Draw indicator of download progress.
191 | */
192 | protected void drawProgressIndicator(Canvas canvas) {
193 | TargetHelper.drawProgressIndicator(canvas, mHandler.getDownloaded(), mHandler.getContentLength());
194 | }
195 | }
--------------------------------------------------------------------------------
/fastimageloader/src/main/java/com/theartofdev/fastimageloader/target/TargetImageViewHandler.java:
--------------------------------------------------------------------------------
1 | // "Therefore those skilled at the unorthodox
2 | // are infinite as heaven and earth,
3 | // inexhaustible as the great rivers.
4 | // When they come to an end,
5 | // they begin again,
6 | // like the days and months;
7 | // they die and are reborn,
8 | // like the four seasons."
9 | //
10 | // - Sun Tsu,
11 | // "The Art of War"
12 |
13 | package com.theartofdev.fastimageloader.target;
14 |
15 | import android.graphics.drawable.Drawable;
16 | import android.text.TextUtils;
17 | import android.view.View;
18 | import android.widget.ImageView;
19 |
20 | import com.theartofdev.fastimageloader.FastImageLoader;
21 | import com.theartofdev.fastimageloader.LoadState;
22 | import com.theartofdev.fastimageloader.LoadedFrom;
23 | import com.theartofdev.fastimageloader.ReusableBitmap;
24 | import com.theartofdev.fastimageloader.Target;
25 | import com.theartofdev.fastimageloader.impl.util.FILLogger;
26 | import com.theartofdev.fastimageloader.impl.util.FILUtils;
27 |
28 | /**
29 | * Handler for loading image as {@link com.theartofdev.fastimageloader.ReusableBitmap} and managing its lifecycle.
30 | * A single instance of the handler should be used for each ImageView.
31 | *
32 | * Use {@link #loadImage(String, String, String, boolean)} to load of image into the
33 | * handler, it will handle cancellation of unfinished requests if a new loading request is given.
34 | *
35 | * The handler attaches itself to ImageView StateChange to update the in-use of the loaded
36 | * bitmap, allowing to reuse bitmaps that are detached from window. This ensures the bitmap is
37 | * reused when the activity/fragment is destroyed.
38 | * On reattach to window if the bitmap was reused the image will be reloaded.
39 | *
40 | * For improved reuse it is advisable to override {@link android.widget.ImageView#onWindowVisibilityChanged(int)}
41 | * method and call {@link #onViewShown()}/{@link #onViewHidden()} on the handler to update in-use state.
42 | *
43 | * {@code protected void onWindowVisibilityChanged(int visibility) {
44 | * super.onWindowVisibilityChanged(visibility);
45 | * if (visibility == VISIBLE) {
46 | * mHandler.onViewShown();
47 | * } else {
48 | * mHandler.onViewHidden();
49 | * }
50 | * }}
51 | *
52 | */
53 | public class TargetImageViewHandler implements Target, View.OnAttachStateChangeListener {
54 |
55 | //region: Fields and Consts
56 |
57 | /**
58 | * the image view
59 | */
60 | protected final ImageView mImageView;
61 |
62 | /**
63 | * The URL source of the image
64 | */
65 | protected String mUrl;
66 |
67 | /**
68 | * the spec to load the image by
69 | */
70 | protected String mSpecKey;
71 |
72 | /**
73 | * The loaded image
74 | */
75 | protected ReusableBitmap mReusableBitmap;
76 |
77 | /**
78 | * Is the recycle bitmap is currently set in use in this image view, so not to set twice
79 | */
80 | protected boolean mInUse;
81 |
82 | /**
83 | * Is the image should be rendered rounded
84 | */
85 | protected boolean mRounded;
86 |
87 | /**
88 | * Is the handled image view should be invalidated on bitmap downloading progress event
89 | */
90 | protected boolean mInvalidateOnDownloading;
91 |
92 | /**
93 | * The current loading states of the image in the handler.
94 | */
95 | protected LoadState mLoadState = LoadState.UNSET;
96 |
97 | /**
98 | * when the image load request started, measure image load request time
99 | */
100 | protected long mStartImageLoadTime;
101 |
102 | /**
103 | * the number of bytes already downloaded, if requested image is downloading
104 | */
105 | protected long mDownloaded;
106 |
107 | /**
108 | * the total number of bytes to download, if requested image is downloading
109 | */
110 | protected long mContentLength;
111 | //endregion
112 |
113 | /**
114 | * @param imageView The image view to handle.
115 | */
116 | public TargetImageViewHandler(ImageView imageView) {
117 | FILUtils.notNull(imageView, "imageView");
118 |
119 | mImageView = imageView;
120 | mImageView.addOnAttachStateChangeListener(this);
121 | }
122 |
123 | /**
124 | * The current loading states of the image in the handler.
125 | */
126 | public LoadState getLoadState() {
127 | return mLoadState;
128 | }
129 |
130 | /**
131 | * Is the drawable is currently animating fade-in of the image
132 | */
133 | public boolean isAnimating() {
134 | Drawable drawable = mImageView.getDrawable();
135 | return drawable != null &&
136 | drawable instanceof AnimatingTargetDrawable &&
137 | ((AnimatingTargetDrawable) drawable).isAnimating();
138 | }
139 |
140 | /**
141 | * Is the image should be rendered rounded
142 | */
143 | public boolean isRounded() {
144 | return mRounded;
145 | }
146 |
147 | /**
148 | * Is the image should be rendered rounded
149 | */
150 | public void setRounded(boolean isRounded) {
151 | mRounded = isRounded;
152 | }
153 |
154 | /**
155 | * Is the handled image view should be invalidated on bitmap downloading progress event
156 | */
157 | public boolean isInvalidateOnDownloading() {
158 | return mInvalidateOnDownloading;
159 | }
160 |
161 | /**
162 | * Is the handled image view should be invalidated on bitmap downloading progress event
163 | */
164 | public void setInvalidateOnDownloading(boolean invalidateOnDownloading) {
165 | mInvalidateOnDownloading = invalidateOnDownloading;
166 | }
167 |
168 | /**
169 | * the number of bytes already downloaded, if requested image is downloading
170 | */
171 | public long getDownloaded() {
172 | return mDownloaded;
173 | }
174 |
175 | /**
176 | * the total number of bytes to download, if requested image is downloading
177 | */
178 | public long getContentLength() {
179 | return mContentLength;
180 | }
181 |
182 | @Override
183 | public String getUri() {
184 | return mUrl;
185 | }
186 |
187 | @Override
188 | public String getSpecKey() {
189 | return mSpecKey;
190 | }
191 |
192 | /**
193 | * See {@link #loadImage(String, String, String, boolean)}.
194 | */
195 | public void loadImage(String url, String specKey) {
196 | loadImage(url, specKey, null, false);
197 | }
198 |
199 | /**
200 | * See {@link #loadImage(String, String, String, boolean)}.
201 | */
202 | public void loadImage(String url, String specKey, String altSpecKey) {
203 | loadImage(url, specKey, altSpecKey, false);
204 | }
205 |
206 | /**
207 | * Load image from the given source.
208 | * If image of the same source is already requested/loaded the request is ignored unless force is true.
209 | *
210 | * @param url the avatar source URL to load from
211 | * @param specKey the spec to load the image by
212 | * @param altSpecKey optional: the spec to use for memory cached image in case the primary is not found.
213 | * @param force true - force image load even if it is the same source
214 | */
215 | public void loadImage(String url, String specKey, String altSpecKey, boolean force) {
216 | FILUtils.notNull(specKey, "spec");
217 |
218 | mDownloaded = 0;
219 | mContentLength = 0;
220 | if (!TextUtils.equals(mUrl, url) || TextUtils.isEmpty(url) || force) {
221 | mStartImageLoadTime = System.currentTimeMillis();
222 | clearImage();
223 |
224 | mUrl = url;
225 | mSpecKey = specKey;
226 |
227 | if (!TextUtils.isEmpty(url)) {
228 | mLoadState = LoadState.LOADING;
229 | FastImageLoader.loadImage(this, altSpecKey);
230 | } else {
231 | clearUsedBitmap();
232 | clearImage();
233 | }
234 | mImageView.invalidate();
235 | }
236 | }
237 |
238 | /**
239 | * Clear the currently used bitmap and mark it as not in use.
240 | */
241 | public void clearUsedBitmap() {
242 | clearUsedBitmap(true);
243 | }
244 |
245 | @Override
246 | public void onBitmapDownloading(long downloaded, long contentLength) {
247 | mDownloaded = downloaded;
248 | mContentLength = contentLength;
249 | if (mInvalidateOnDownloading) {
250 | mImageView.postInvalidate();
251 | }
252 | }
253 |
254 | @Override
255 | public void onBitmapLoaded(ReusableBitmap bitmap, LoadedFrom from) {
256 |
257 | clearUsedBitmap(false);
258 |
259 | mLoadState = LoadState.LOADED;
260 |
261 | mInUse = true;
262 | mReusableBitmap = bitmap;
263 | mReusableBitmap.incrementInUse();
264 |
265 | setImage(bitmap, from);
266 |
267 | FILLogger.operation(mUrl, mSpecKey, from, true, System.currentTimeMillis() - mStartImageLoadTime);
268 | }
269 |
270 | @Override
271 | public void onBitmapFailed() {
272 | String url = mUrl;
273 | String specKey = mSpecKey;
274 | mLoadState = LoadState.FAILED;
275 | if (mImageView.getDrawable() == null) {
276 | clearImage();
277 | mUrl = url;
278 | mSpecKey = specKey;
279 | mImageView.invalidate();
280 | }
281 | FILLogger.operation(url, specKey, null, false, System.currentTimeMillis() - mStartImageLoadTime);
282 | }
283 |
284 | /**
285 | * Handle Image View visibility change by updating the used bitmap.
286 | * If the Image View is hidden then we decrement the in-use.
287 | * If the Image View is shown we use the existing bitmap or reload the image.
288 | */
289 | public void onViewVisibilityChanged(int visibility) {
290 | if (visibility == View.VISIBLE) {
291 | onViewShown();
292 | } else {
293 | onViewHidden();
294 | }
295 | }
296 |
297 | /**
298 | * On attach of the ImageView to window call {@link #onViewShown()}.
299 | */
300 | @Override
301 | public void onViewAttachedToWindow(View v) {
302 | onViewShown();
303 | }
304 |
305 | /**
306 | * On detach of the ImageView from window call {@link #onViewHidden()}.
307 | */
308 | @Override
309 | public void onViewDetachedFromWindow(View v) {
310 | onViewHidden();
311 | }
312 |
313 | /**
314 | * On image view shown verify that the set bitmap is still valid for the image view (not reused).
315 | * If valid: set in-use on the bitmap.
316 | * If not valid: execute image load request to re-load the image needed for the image view.
317 | */
318 | protected void onViewShown() {
319 | if (mReusableBitmap != null && !mInUse) {
320 | if (TextUtils.equals(mReusableBitmap.getUri(), mUrl)) {
321 | mInUse = true;
322 | mReusableBitmap.incrementInUse();
323 | } else {
324 | FILLogger.info("ImageView attachToWindow uses recycled bitmap, reload... [{}]", mReusableBitmap);
325 | loadImage(mUrl, mSpecKey, null, true);
326 | }
327 | }
328 | }
329 |
330 | /**
331 | * On image view hidden set the used bitmap to not-in-use so it can be reused.
332 | */
333 | protected void onViewHidden() {
334 | if (mReusableBitmap != null && mInUse) {
335 | mInUse = false;
336 | mReusableBitmap.decrementInUse();
337 | }
338 | }
339 |
340 | /**
341 | * Release the resource, unregister from state change.
342 | */
343 | public void close() {
344 | clearUsedBitmap();
345 | mImageView.removeOnAttachStateChangeListener(this);
346 | }
347 |
348 | /**
349 | * Called to clear the existing image in the handled image view.
350 | * Called on loading or failure.
351 | */
352 | protected void clearImage() {
353 | mImageView.setImageDrawable(null);
354 | }
355 |
356 | /**
357 | * Called to set the loaded image bitmap in the handled image view.
358 | */
359 | protected void setImage(ReusableBitmap bitmap, LoadedFrom from) {
360 | boolean showFade = from == LoadedFrom.NETWORK && mImageView.getDrawable() == null;
361 | Drawable drawable = mRounded
362 | ? new TargetCircleDrawable(bitmap.getBitmap(), from, showFade)
363 | : new TargetDrawable(bitmap.getBitmap(), from, showFade);
364 | mImageView.setImageDrawable(drawable);
365 | }
366 |
367 | /**
368 | * Clear the currently used bitmap and mark it as not in use.
369 | */
370 | protected void clearUsedBitmap(boolean full) {
371 | if (full) {
372 | mUrl = null;
373 | mSpecKey = null;
374 | }
375 | mLoadState = LoadState.UNSET;
376 | if (mReusableBitmap != null) {
377 | if (mInUse) {
378 | mInUse = false;
379 | mReusableBitmap.decrementInUse();
380 | }
381 | mReusableBitmap = null;
382 | }
383 | }
384 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ArthurHub/Android-Fast-Image-Loader/b794be15c2ddaf3157bdb27ef9ec32995f3f5266/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Apr 10 15:27:10 PDT 2013
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/license.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Arthur Teplitzki
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':demo', ':fastimageloader'
2 |
--------------------------------------------------------------------------------