package com.evancharlton.mileage.adapters; import com.evancharlton.mileage.R; import com.evancharlton.mileage.dao.CachedValue; import com.evancharlton.mileage.dao.Vehicle; import com.evancharlton.mileage.provider.Statistic; import com.evancharlton.mileage.provider.Statistics; import com.evancharlton.mileage.provider.StatisticsGroup; import com.evancharlton.mileage.provider.tables.CacheTable; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import java.util.ArrayList; import java.util.HashMap; public class VehicleStatisticsAdapter extends BaseAdapter { private static final String TAG = "VehicleStatisticsAdapter"; private static final int TYPE_STATISTIC = 0; private static final int TYPE_GROUP = 1; private final ArrayList<StatisticHolder> mObjects = new ArrayList<StatisticHolder>(); private final HashMap<String, String> mValues = new HashMap<String, String>(); private final Context mContext; private final Vehicle mVehicle; private final LayoutInflater mInflater; public VehicleStatisticsAdapter(Context context, Vehicle vehicle, StatisticsGroup[] groups) { mInflater = LayoutInflater.from(context); mContext = context; mVehicle = vehicle; for (StatisticsGroup group : groups) { mObjects.add(new StatisticHolder(context, group)); for (Statistic statistic : group.getStatistics()) { mObjects.add(new StatisticHolder(context, statistic, vehicle)); } } } public void setValue(Statistic statistic, double value) { setValue(statistic, statistic.format(mContext, mVehicle, value)); } public void setValue(Statistic statistic, String value) { mValues.put(statistic.getKey(), value); } public int getNumHeadersAbove(int position) { int total = 0; for (int i = position - 1; i >= 0; i--) { if (getItemViewType(i) == TYPE_GROUP) { total++; } } return total; } public void flush() { // flush the statistics to disk new Thread() { @Override public void run() { Log.d(TAG, "Erasing the cache ..."); // erase the existing cache String where = CachedValue.ITEM + " = ?"; String[] selectionArgs = new String[] { String.valueOf(mVehicle.getId()) }; mContext.getContentResolver().delete(CacheTable.BASE_URI, where, selectionArgs); Log.d(TAG, "Building new values ..."); // write the new cache ContentValues[] values = new ContentValues[Statistics.STATISTICS.size()]; final int length = mObjects.size(); final long vehicleId = mVehicle.getId(); int num = 0; for (int i = 0; i < length; i++) { StatisticHolder holder = mObjects.get(i); if (holder.type == TYPE_STATISTIC) { ContentValues v = new ContentValues(); v.put(CachedValue.ITEM, vehicleId); v.put(CachedValue.VALID, true); v.put(CachedValue.VALUE, mValues.get(holder.key)); v.put(CachedValue.KEY, holder.key); values[num++] = v; } } if (num != values.length) { Log.d(TAG, "Not writing to the database because we don't have all the stats"); } else { Log.d(TAG, "Writing " + num + " records to the database ..."); long start = System.currentTimeMillis(); mContext.getContentResolver().bulkInsert(CacheTable.BASE_URI, values); long diff = System.currentTimeMillis() - start; double seconds = diff / 1000D; Log.d(TAG, "Caching of " + num + " records complete! (" + seconds + " seconds)"); } } }.start(); } public void changeCursor(Cursor cursor) { // TODO(3.1) - This isn't efficient and it runs on the UI thread. Boo! cursor.moveToPosition(-1); final int key_position = cursor.getColumnIndex(CachedValue.KEY); final int value_position = cursor.getColumnIndex(CachedValue.VALUE); while (cursor.moveToNext()) { String key = cursor.getString(key_position); String value = cursor.getString(value_position); mValues.put(key, value); } notifyDataSetChanged(); } @Override public int getCount() { return mObjects.size(); } @Override public Object getItem(int position) { return mObjects.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { StatisticHolder holder = mObjects.get(position); if (convertView == null) { switch (holder.type) { case TYPE_STATISTIC: convertView = mInflater.inflate(R.layout.statistic, parent, false); break; case TYPE_GROUP: convertView = mInflater.inflate(R.layout.divider, parent, false); break; } } ViewHolder viewHolder = (ViewHolder) convertView.getTag(); if (viewHolder == null) { viewHolder = new ViewHolder(convertView); } switch (holder.type) { case TYPE_STATISTIC: viewHolder.text.setText(holder.text); viewHolder.value.setText(mValues.get(holder.key)); break; case TYPE_GROUP: viewHolder.text.setText(holder.text); break; } return convertView; } @Override public int getViewTypeCount() { return 2; } @Override public int getItemViewType(int position) { return mObjects.get(position).type; } @Override public boolean isEnabled(int position) { return getItemViewType(position) == TYPE_STATISTIC; } private static class StatisticHolder { public final String key; public final String text; public final int type; public StatisticHolder(Context context, Statistic statistic, Vehicle vehicle) { key = statistic.getKey(); text = statistic.getLabel(context, vehicle); type = TYPE_STATISTIC; } public StatisticHolder(Context context, StatisticsGroup group) { key = null; text = context.getString(group.getLabel()); type = TYPE_GROUP; } } private static class ViewHolder { public final TextView text; public final TextView value; public ViewHolder(View convertView) { text = (TextView) convertView.findViewById(android.R.id.text1); value = (TextView) convertView.findViewById(android.R.id.text2); convertView.setTag(this); } } }