/** * */ package com.todoroo.astrid.helper; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import android.content.Intent; import android.support.v4.app.ListFragment; import android.widget.ListView; import com.todoroo.astrid.adapter.TaskAdapter.ViewHolder; import com.todoroo.astrid.api.AstridApiConstants; import com.todoroo.astrid.data.Task; abstract public class TaskAdapterAddOnManager<TYPE> { private final ListFragment fragment; /** * @param taskAdapter */ protected TaskAdapterAddOnManager(ListFragment fragment) { this.fragment = fragment; } private final Map<Long, LinkedHashMap<String, TYPE>> cache = Collections.synchronizedMap(new HashMap<Long, LinkedHashMap<String, TYPE>>(0)); // --- interface /** * Request add-ons for the given task * @return true if cache miss, false if cache hit */ public boolean request(ViewHolder viewHolder) { long taskId = viewHolder.task.getId(); Collection<TYPE> list = initialize(taskId); if(list != null) { draw(viewHolder, taskId, list); return false; } // request details draw(viewHolder, taskId, get(taskId)); Intent broadcastIntent = createBroadcastIntent(viewHolder.task); if(broadcastIntent != null) fragment.getActivity().sendOrderedBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ); return true; } /** creates a broadcast intent for requesting */ abstract protected Intent createBroadcastIntent(Task task); /** updates the given view */ abstract protected void draw(ViewHolder viewHolder, long taskId, Collection<TYPE> list); /** resets the view as if there was nothing */ abstract protected void reset(ViewHolder viewHolder, long taskId); /** on receive an intent */ public void addNew(long taskId, String addOn, TYPE item, ViewHolder thisViewHolder) { if(item == null) return; Collection<TYPE> cacheList = addIfNotExists(taskId, addOn, item); if(cacheList != null) { if(thisViewHolder != null) draw(thisViewHolder, taskId, cacheList); else { ListView listView = fragment.getListView(); // update view if it is visible int length = listView.getChildCount(); for(int i = 0; i < length; i++) { ViewHolder viewHolder = (ViewHolder) listView.getChildAt(i).getTag(); if(viewHolder == null || viewHolder.task.getId() != taskId) continue; draw(viewHolder, taskId, cacheList); break; } } } } /** * Clears the cache */ public void clearCache() { cache.clear(); } /** * Clears single item from cache */ public void clearCache(long taskId) { cache.remove(taskId); } // --- internal goodies /** * Retrieves a list. If it doesn't exist, list is created, but * the method will return null * @param taskId * @return list if there was already one */ protected synchronized Collection<TYPE> initialize(long taskId) { if(cache.containsKey(taskId) && cache.get(taskId) != null) return get(taskId); cache.put(taskId, new LinkedHashMap<String, TYPE>(0)); return null; } /** * Adds an item to the cache if it doesn't exist * @param taskId * @param item * @return iterator if item was added, null if it already existed */ protected synchronized Collection<TYPE> addIfNotExists(long taskId, String addOn, TYPE item) { LinkedHashMap<String, TYPE> list = cache.get(taskId); if(list == null) return null; if(list.containsValue(item)) return null; list.put(addOn, item); return get(taskId); } /** * Gets an item at the given index * @param taskId * @return */ protected Collection<TYPE> get(long taskId) { if(cache.get(taskId) == null) return null; return cache.get(taskId).values(); } }