This repository was archived by the owner on Sep 1, 2020. It is now read-only.
Repository navigation
Expand file tree
/
Copy pathLazyImageView.mirah
More file actions
244 lines (205 loc) · 6.23 KB
/
Copy pathLazyImageView.mirah
File metadata and controls
244 lines (205 loc) · 6.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.drawable.Drawable
import android.os.Environment
import android.os.Handler
import android.os.Handler.Callback
import android.os.Message
import android.util.Log
import android.widget.ImageView
import java.io.File
import java.io.FileNotFoundException
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
class LazyImageView < ImageView
implements Callback
def initialize(context:Context, placeholder:int)
super context
@context = context
@placeholder = placeholder
@src_url = String(nil)
@path = String(nil)
@loaded = false
@resizing = false
setImageResource @placeholder
end
def self.cache_dir(c:Context):File
@cache_dir ||= File.new(c.getCacheDir, "lazy_image_cache")
@cache_dir.mkdirs unless @cache_dir.exists
@cache_dir
end
def self.purgeDiskCache(c:Context):void
thread = Thread.new do
oldest_acceptable = System.currentTimeMillis
10.times do
Log.d 'LazyImageView', 'NOTE: Deleting ALL cached images. Uncomment the next line for a real application.'
end
# 8 hours
# oldest_acceptable = System.currentTimeMillis - long(28800000)
d = LazyImageView.cache_dir(c)
files = d.listFiles unless d.nil?
unless files.nil?
files.each do |f|
begin
# Skip nils, directories, and current files.
next if f.nil? || (!f.isFile) || f.lastModified >= oldest_acceptable
Log.v "LazyImageView", "D " + f.getCanonicalPath
f.delete
rescue IOException => e
Log.e "LazyImageView", "purgeDiskCache: Error checking or deleting cache file:", e
end
end
end
end
# Do this on a different thread
LazyGalleryActivity.threadPoolExecutor.execute thread
end
def cache_dir:File
LazyImageView.cache_dir(@context)
end
# Make this a no-op to keep selected state when updating in the background.
$Override
def requestLayout:void
end
def refresh:void
unless display_from_path()
setImageResource @placeholder
end
end
def getPlaceholder
@placeholder
end
def setPlaceholder(placeholder:int)
@placeholder = placeholder
end
def setSrcUrl(url:String):void
@src_url = url
@path = File.new(cache_dir, "" + @src_url.hashCode + ".jpg").getCanonicalPath
end
def getSrcUrl
@src_url
end
def load:void
unless @loaded || @src_url.nil? || @path.nil?
AsyncDownload.new(Handler.new(self), @src_url, @path)
end
end
def handleMessage(message:Message)
result = false
if (!message.nil?) && message.what == 0
# Make sure this update is from the current path.
if @path.equals message.obj
result = true
refresh()
end
end
return result
end
protected
def display_from_path
d = safe_image_to_drawable(@path, 180)
unless d.nil?
setImageDrawable(d)
@loaded = true
else
@resizing = false
@loaded = false
end
return @loaded
end
#
# Loads a Drawable from the given path, scaling it if it's too large.
#
def safe_image_to_drawable(path:String, target_size:int):Drawable
drawable = Drawable(nil)
return drawable if path.nil?
begin
# Short-circuits here if file not found.
fis = FileInputStream.new(path)
o = BitmapFactory.Options.new
# To check on-disk image dimensions without loading pixels.
o.inJustDecodeBounds = true
BitmapFactory.decodeStream(fis, nil, o)
fis.close
tw = o.outWidth
th = o.outHeight
if tw > target_size * 2 && th > target_size * 2
# Resize is necessary. Do it on another thread.
unless @resizing
AsyncResize.new(Handler.new(self), path, target_size)
@resizing = true
end
drawable = Drawable(nil)
else
# Size verified - load a drawable.
drawable = Drawable.createFromPath path
end
rescue FileNotFoundException => e
# No file? No problem. It still needs to be downloaded.
ensure
fis.close unless fis.nil?
end
return drawable
end
class AsyncResize
implements Runnable
def initialize(handler:Handler, path:String, target_size:int)
@handler = handler
@path = path
@target_size = target_size
LazyGalleryActivity.threadPoolExecutor.execute self
end
def run:void
success = false
begin
fis = FileInputStream.new(@path)
o = BitmapFactory.Options.new
# To check on-disk image dimensions without loading pixels.
o.inJustDecodeBounds = true
BitmapFactory.decodeStream(fis, nil, o)
fis.close
tw = o.outWidth
th = o.outHeight
# Don't re-resize.
if tw > @target_size * 2 && th > @target_size * 2
scale = 1
while tw/2 > @target_size && th/2 > @target_size
tw /= 2
th /= 2
scale *= 2
end
Log.v "AsyncResize", "Scaling " + o.outWidth + "x" + o.outHeight + " by factor of " + scale + "..."
fis = FileInputStream.new(@path)
o = BitmapFactory.Options.new
o.inSampleSize = scale
bitmap = BitmapFactory.decodeStream(fis, nil, o)
Log.v "AsyncResize", "\tscaled to " + tw + "x" + th
# Write scaled version out
unless bitmap.nil?
fos = FileOutputStream.new(@path)
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos)
Log.v "AsyncResize", "\tsaved to " + @path
success = true
end
end
rescue FileNotFoundException => e
# No file? No problem. It still needs to be downloaded.
rescue IOException => e
# TODO
Log.e "AsyncResize", "Bitmap Resize Failed", e
# delete path?
ensure
fis.close unless fis.nil?
fos.close unless fos.nil?
bitmap.recycle unless bitmap.nil?
end
if success
@handler.sendMessage(@handler.obtainMessage(0, @path))
else
@handler.sendEmptyMessage(1)
end
end
end
end