@myron-lee
2015-01-14T12:53:18.000000Z
字数 8455
阅读 1951
每日记录
昨晚看了爆裂鼓手,励志,今天干劲十足。早上,康康夸我是个自律的人。非常高兴,因为觉得自律的人肯定会成功。
存储图片文件夹的相关信息,包括路径、名称、包含图片数量、第一张图片的路径等信息。
抽象 ViewHolder 模式,方便编码。但是方便程度有限。里面用到了我没用过的容器SparseArray,作者把它当做 map 一样使用。
public <T extends View> T getView(int viewId)
{
View view = mViews.get(viewId);
if (view == null)
{
view = mConvertView.findViewById(viewId);
mViews.put(viewId, view);
}
return (T) view;
}
按照文档的说法,SparseArray是用时间换空间,适用于元素较少的情况。
SparseArrays map integers to Objects. Unlike a normal array of Objects, there can be gaps in the indices. It is intended to be more memory efficient than using a HashMap to map Integers to Objects, both because it avoids auto-boxing keys and its data structure doesn't rely on an extra entry object for each mapping.
Note that this container keeps its mappings in an array data structure, using a binary search to find keys. The implementation is not intended to be appropriate for data structures that may contain large numbers of items. It is generally slower than a traditional HashMap, since lookups require a binary search and adds and removes require inserting and deleting entries in the array. For containers holding up to hundreds of items, the performance difference is not significant, less than 50%.
To help with performance, the container includes an optimization when removing keys: instead of compacting its array immediately, it leaves the removed entry marked as deleted. The entry can then be re-used for the same key, or compacted later in a single garbage collection step of all removed entries. This garbage collection will need to be performed at any time the array needs to be grown or the the map size or entry values are retrieved.
It is possible to iterate over the items in this container using keyAt(int) and valueAt(int). Iterating over the keys using keyAt(int) with ascending values of the index will return the keys in ascending order, or the values corresponding to the keys in ascending order in the case of valueAt(int).
和 ViewHolder 配合使用,快速的创建适配器。
作者自己实现的图片加载器,使用了很多缓存技术。
根据文档,这个类提供的缓存功能。如果存储已满,最不常用的项将被剔除。可以继承这个类,重写一些方法,对项将被剔除、项没有击中等情况做额外处理。可以规定缓存占用存储的大小。另外,它是多线程安全的。null 不能作为 key 或者 value。
A cache that holds strong references to a limited number of values. Each time a value is accessed, it is moved to the head of a queue. When a value is added to a full cache, the value at the end of that queue is evicted and may become eligible for garbage collection.
If your cached values hold resources that need to be explicitly released, override entryRemoved(boolean, K, V, V).
If a cache miss should be computed on demand for the corresponding keys, override create(K). This simplifies the calling code, allowing it to assume a value will always be returned, even when there's a cache miss.
By default, the cache size is measured in the number of entries. Override sizeOf(K, V) to size the cache in different units. For example, this cache is limited to 4MiB of bitmaps:
int cacheSize = 4 * 1024 * 1024; // 4MiB
LruCache bitmapCache = new LruCache(cacheSize) {
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}}
This class is thread-safe. Perform multiple cache operations atomically by synchronizing on the cache:synchronized (cache) {
if (cache.get(key) == null) {
cache.put(key, value);}}
This class does not allow null to be used as a key or value. A return value of null from get(K), put(K, V) or remove(K) is unambiguous: the key was not in the cache.This class appeared in Android 3.1 (Honeycomb MR1); it's available as part of Android's Support Package for earlier releases.
它提供了两类方法,一是管理异步任务的终止,二是跟踪异步任务的过程。为了回收资源,使用过的ExecutorService应该终止,有普通终止和立即终止两种方式。submit 方法创建并返回 Future,用于终止运行或者等待运行结束。invokeAny,invokeAll用于大量的运行
An Executor that provides methods to manage termination and methods that can produce a Future for tracking progress of one or more asynchronous tasks.
An ExecutorService can be shut down, which will cause it to reject new tasks. Two different methods are provided for shutting down an ExecutorService. The shutdown() method will allow previously submitted tasks to execute before terminating, while the shutdownNow() method prevents waiting tasks from starting and attempts to stop currently executing tasks. Upon termination, an executor has no tasks actively executing, no tasks awaiting execution, and no new tasks can be submitted. An unused ExecutorService should be shut down to allow reclamation of its resources.Method submit extends base method execute(Runnable) by creating and returning a Future that can be used to cancel execution and/or wait for completion. Methods invokeAny and invokeAll perform the most commonly useful forms of bulk execution, executing a collection of tasks and then waiting for at least one, or all, to complete. (Class ExecutorCompletionService can be used to write customized variants of these methods.)
The Executors class provides factory methods for the executor services provided in this package.
Usage Examples
Here is a sketch of a network service in which threads in a thread pool service incoming requests. It uses the preconfigured newFixedThreadPool(int) factory method:
class NetworkService implements Runnable {
private final ServerSocket serverSocket;
private final ExecutorService pool;
public NetworkService(int port, int poolSize)
throws IOException {
serverSocket = new ServerSocket(port);
pool = Executors.newFixedThreadPool(poolSize);
public void run() { // run the service
try {
for (;;) {
pool.execute(new Handler(serverSocket.accept()));
}
} catch (IOException ex) {
pool.shutdown();
}
}
}
class Handler implements Runnable {
private final Socket socket;
Handler(Socket socket) { this.socket = socket; }
public void run() {
// read and service request on socket
}
}}
The following method shuts down an ExecutorService in two phases, first by calling shutdown to reject incoming tasks, and then calling shutdownNow, if necessary, to cancel any lingering tasks:
void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}}
Memory consistency effects: Actions in a thread prior to the submission of a Runnable or Callable task to an ExecutorService happen-before any actions taken by that task, which in turn happen-before the result is retrieved via Future.get().
为了实现这一虚拟文件夹,需要很多改动。因为,这个‘文件夹’里的图片不属于统一路径。mImgs 里必须包含路径名,而不仅仅是文件名了。
我的修改
//add dir, 傻!!,你取了元素,没有赋值回去啊
for (String img : selectedImgs){
img = floder.getDir() + "/" + img;
}
String dirPrefix = floder.getDir() + "/";
for (int i = 0; i < selectedImgs.size(); i++) {
selectedImgs.set(i, dirPrefix + selectedImgs.get(i));
}
使用 file 的这个函数,public long lastModified()
,得到它的最后修改时间。然后使用Collections.sort()
对image
进行排序。
问题:照相连拍,得到的图片,其 lastModified 值相同,排序出现问题。
问题解决:
Collections.sort(mImgs, new Comparator<String>() {
@Override
public int compare(String lhs, String rhs) {
long rTime = imgLastModifiedTime.get(rhs);
long lTime = imgLastModifiedTime.get(lhs);
if (rTime < lTime){
return -1;
} else if (rTime == lTime) {
return 0;
} else {
return 1;
}
}
});
成功
Collections.sort(mImgs, new Comparator<String>() {
@Override
public int compare(String lhs, String rhs) {
return (int) (imgLastModifiedTime.get(rhs) - imgLastModifiedTime.get(lhs));
}
});
失败
I don't know why !
这样不好。改变数据之后,调用 adapter 的 notifyDataSetChanged 就可以。
两个函数值得收藏
private List<String> getImgs(ImageFloder floder) {
List<String> imgs = new ArrayList<String>();
String[] imgNames = new File(floder.getDir()).list(new FilenameFilter() {
@Override
public boolean accept(File dir, String filename) {
if (filename.endsWith(".jpg") || filename.endsWith(".png")
|| filename.endsWith(".jpeg"))
return true;
return false;
}
});
String dirPrefix = floder.getDir() + "/";
for (int i = 0; i < imgNames.length; i++) {
imgs.add(dirPrefix + imgNames[i]);
}
return imgs;
}
private void sortImg(List<String> imgs) {
//Sort the image, descending in time.
final Map<String, Long> imgLastModifiedTime = new HashMap<String, Long>();
for (String img : imgs){
File file = new File(img);
imgLastModifiedTime.put(img, file.lastModified());
}
Collections.sort(imgs, new Comparator<String>() {
@Override
public int compare(String lhs, String rhs) {
long rTime = imgLastModifiedTime.get(rhs);
long lTime = imgLastModifiedTime.get(lhs);
if (rTime < lTime) {
return -1;
} else if (rTime == lTime) {
return 0;
} else {
return 1;
}
}
});
}
<application
android:allowBackup="true"
android:icon="@drawable/logo"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
快速设置 App 的 icon 和 name
imageview backgroud ???