gt:           	    final int[] location = new int[2];
context: package mobi.intuitit.android.widget;
  
  import java.util.ArrayList;
  import java.util.HashMap;
  
  import android.app.PendingIntent;
  import android.content.Context;
  import android.content.Intent;
  import android.database.Cursor;
  import android.graphics.Bitmap;
  import android.graphics.BitmapFactory;
  import android.graphics.Rect;
  import android.net.Uri;
  import android.os.Parcel;
  import android.os.Parcelable;
  import android.view.View;
  import android.view.View.OnClickListener;
  
  public class BoundRemoteViews extends SimpleRemoteViews {
  
  	class CursorCache {
  
  		final ArrayList<HashMap<Action, Object>> mCache;
  		final HashMap<Action, Object> mDefaults;
  
  		public Object getValueOrDefault(int index, Action target) {
  			HashMap<Action, Object> row = mCache.get(index);
  			Object result = null;
  			if (row.containsKey(target))
  				 result = row.get(target);
  			if (result == null)
  				result = mDefaults.get(target);
  			return result;
  		}
  
  		public CursorCache(Cursor cursor, Context context) {
  			final int cacheSize = cursor != null ? cursor.getCount() : 0;
  
  			mCache = new ArrayList<HashMap<Action,Object>>(cacheSize);
  			mDefaults = new HashMap<Action, Object>();
  
  			final ArrayList<Action> actions = BoundRemoteViews.this.mActions;
  
  			for (int i = 0; i < actions.size(); i++) {
  				Action act = actions.get(i);
  				if (act instanceof BindingAction)
  					mDefaults.put(act, ((BindingAction)act).getDefault(context));
  				else if (act instanceof SetBoundOnClickIntent)
  					mDefaults.put(act, null);
  			}
  			if (cursor != null) {
  				cursor.moveToFirst();
  
  				while(!cursor.isAfterLast()) {
  
  					HashMap<Action, Object> row = new HashMap<Action, Object>();
  
  
  					for (int i = 0; i < actions.size(); i++) {
  						Action act = actions.get(i);
  						if (act instanceof BindingAction)
  							row.put(act, ((BindingAction)act).readValue(cursor, context));
  						else if (act instanceof SetBoundOnClickIntent)
  							row.put(act, ((SetBoundOnClickIntent)act).readValue(cursor));
  					}
  
  					mCache.add(row);
  					cursor.moveToNext();
  				}
  			}
  		}
  
  		private void dropCacheRow(HashMap<Action,Object> row) {
  			for(Action key : row.keySet()) {
  				Object value = row.get(key);
  				if (value instanceof Bitmap) {
  					((Bitmap)value).recycle();
  				}
  			}
  			row.clear();
  		}
  
  		public void clear() {
  			for(HashMap<Action, Object> row : mCache) {
  				dropCacheRow(row);
  			}
  			mCache.clear();
  			dropCacheRow(mDefaults);
  		}
  	}
  
  
  	protected class BindingAction extends SimpleRemoteViews.ReflectionAction
  	{
  		public static final int tag = 99;
  
  		private int mCursorIndex;
  		private int mDefaultResource;
  
  		public BindingAction(int viewId, String methodName, int type, int cursorIndex, int defaultResource) {
  			super(viewId, methodName, type);
  			mCursorIndex = cursorIndex;
  			mDefaultResource = defaultResource;
  	    }
  
  		public BindingAction(Parcel in) {
  			super(in);
  		}
  
  		@Override
  	    protected int getTag() {
  	    	return tag;
  	    }
  
  		@Override
  		protected void readValue(Parcel in) {
  			mCursorIndex = in.readInt();
  			mDefaultResource = in.readInt();
  		}
  
  		@Override
  		protected void writeValue(Parcel out, int flags) {
  			out.writeInt(mCursorIndex);
  			out.writeInt(mDefaultResource);
  		}
  
  		@Override
  		protected Object getValue(Context context) {
  			return mCursor.getValueOrDefault(mCursorPos, this);
  		}
  
  		public Object readValue(Cursor cursor, Context context) {
  			try
  			{
  				switch(this.type) {
  					case STRING:
  					case CHAR_SEQUENCE:
  						return cursor.getString(mCursorIndex);
  					case BYTE:
  						return (byte)cursor.getInt(mCursorIndex);
  					case SHORT:
  						return (short)cursor.getInt(mCursorIndex);
  					case INT:
  						return cursor.getInt(mCursorIndex);
  					case LONG:
  						return cursor.getLong(mCursorIndex);
  					case FLOAT:
  						return cursor.getFloat(mCursorIndex);
  					case DOUBLE:
  						return cursor.getDouble(mCursorIndex);
  					case CHAR:
  						return cursor.getString(mCursorIndex).charAt(0);
  					case URI:
  						return Uri.parse(cursor.getString(mCursorIndex));
  					case BITMAP:
  						byte[] blob = cursor.getBlob(mCursorIndex);
  		                return BitmapFactory.decodeByteArray(blob, 0, blob.length);
  				}
  			}
  			catch(Exception e) {
  				return null;
  			}
  			return null;
  		}
  
  		public Object getDefault(Context context) {
  			try
  			{
  				switch(this.type) {
  					case STRING:
  					case CHAR_SEQUENCE:
  						return context.getString(mDefaultResource);
  					case BITMAP:
  						return BitmapFactory.decodeResource(context.getResources(), mDefaultResource);
  				}
  			}
  			catch(Exception e) {
  				return null;
  			}
  			return null;
  		}
  
  		@Override
  		public void apply(View root) {
  			super.apply(root);
  		}
  	}
  
  	protected class SetBoundOnClickIntent extends Action {
  		private static final int TAG = 100;
  
  		private final String mExtraName;
  		private final int mExtraCursorIndex;
  		private final int mViewId;
  		private final PendingIntent mIntent;
  
          public SetBoundOnClickIntent(int id, PendingIntent intent,
          		String extraName, int extraCursorIndex) {
          	mViewId = id;
          	mIntent = intent;
          	mExtraName = extraName;
          	mExtraCursorIndex = extraCursorIndex;
          }
  
          public SetBoundOnClickIntent(Parcel parcel) {
          	mViewId = parcel.readInt();
          	mExtraName = parcel.readString();
          	mExtraCursorIndex = parcel.readInt();
          	mIntent = PendingIntent.CREATOR.createFromParcel(parcel);
          }
  
          public void writeToParcel(Parcel dest, int flags) {
              dest.writeInt(TAG);
              dest.writeInt(mViewId);
              dest.writeString(mExtraName);
              dest.writeInt(mExtraCursorIndex);
              mIntent.writeToParcel(dest, 0 /* no flags */);
          }
  
          @Override
          public void apply(View root) {
              final View target = root.findViewById(mViewId);
              if (target != null && mIntent != null) {
                  target.setOnClickListener(new BoundOnClickListener(mCursorPos));
              }
          }
  
          private class BoundOnClickListener implements OnClickListener {
  
          	private final int myCursorPos;
  
          	public BoundOnClickListener(int cursorPos) {
          		myCursorPos = cursorPos;
          	}
  
          	public void onClick(View v) {
                  // Find target view location in screen coordinates and
                  // fill into PendingIntent before sending.
  