一种更清洁的方式来转变" Pojo(s)中的游标

时间:2014-03-14 21:34:13

标签: android sqlite cursor android-cursoradapter

我做了很多使用SQLite的应用程序,而且经常无法设计数据库,因为我必须使用客户定义的Schema。

显然:-用户体验/用户界面设计师并不关心基础数据......她/他必须很酷!

所以我,不经常使用大量INNER JOINLEFT JOIN和非常大的SQL查询(但由于ContentProviders和Services的强大功能,这不是一个大问题。)< / p>

让我烦恼的是用于处理来自所有适配器.getItem(position)的不同Cursor的“剪切/粘贴”(或静态最终)代码。

所以我想到了一种让事情更加清洁的方法,就像这样。

CursorHandler.java

此接口的实现将Cursor转换为对象。 T 是输入Cursor将转换为的目标类型。

public interface CursorHandler<T> {
   T handle(Cursor cu)
}

CursorHandlerAdapter.java

创建一个自定义CursorAdapter,它将使用上面的接口自动将游标转换为指定的pojo

abstract
public class CursorHandlerAdapter<T> extends CursorAdapter {

   private LayoutInflater    mInflater  = null;
   private CursorHandler<T>  mHandler   = null;

   public CursorHandlerAdapter(Context context, CursorHandler<T> handler) {
     super(context, null, 0);
     mHandler  = handler;
     mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
   }

   @Override
   public T getItem(int position) {
     Cursor cu = (Cursor)super.getItem(position);
     return ((cu == null) ? null : mHandler.handle(cu));
   }


   protected T getItem(Cursor cu) {
     return mHandler.handle(cu);
   }

   protected LayoutInflater getLayoutInflater() { return mInflater; }   
};

用法示例

假设我们有一个pojo,我们称之为 Item

public class Item  implements Parcelable {

   public long     id;
   public String   code;
   public String   title;
   public String   description;
   public String   imageUrl;

   public Item() {  }

   @Override
   public String toString() {
      StringBuilder sb = new StringBuilder("[");
      sb.append("id=");
      sb.append(this.id);
      sb.append(", ");
      /* append the others fields */
      return sb.toString();
   }

   @Override
   public boolean equals(Object obj) {
      if (obj == null) return false;
      if (obj == this) return true;
      if (!(obj instanceof Item)) return false;

      Item test = (Item)obj;

      boolean result = true;
      result = result && (this.code == test.code || 
         (this.code != null && this.code.equals(test.code)));
      return result;
   }

   @Override
   public int hashCode() {
      int result = 8;
      result = 31 * result + (this.code == null ? 0 : this.code.hashCode());
      return result;    
   }

   @Override
   public void writeToParcel(Parcel parcel, int flags) {
      parcel.writeLong(this.id);
      parcel.writeString(this.code);
      /* write the others fields */
   }

   static final
   public Creator<Item> CREATOR = new Creator<Item>() {
      @Override
      public Item createFromParcel(Parcel source) {
         return new Item(source);
      }

      @Override
      public Item[] newArray(int size) {
         return new Item[size];
      }
   };

   private Item(Parcel in) {
      this.id = in.readLong();
      this.code = in.readString();
      /* read the others fields */
   }
};

让我们创建我们的CursorHandler实现:

public class ItemCursorHandler implements CursorHandler<Item> {

   @Override
   public Item handle(Cursor cu) throws SQLException {
      Item item = new Item();

      int idx = cu.getColumnIndex(CommonsColumns.ID);
      if (idx != -1)
         item.id = cu.getLong(idx);

      idx = cu.getColumnIndex(ItemColumns.CODE);
      if (idx != -1)
         item.code = cu.getString(idx);

      idx = cu.getColumnIndex(ItemColumns.TITLE);
      if (idx != -1)
         item.title = cu.getString(idx);

      idx = cu.getColumnIndex(ItemColumns.DESCRIPTION);
      if (idx != -1)
         item.description = cu.getString(idx);

      idx = cu.getColumnIndex(ItemColumns.IMAGE_URL);
      if (idx != -1)
         item.imageUrl = cu.getString(idx);

      return item;
   }
}

然后,相关的CursorAdapter:

public class ItemsCursorAdapter extends CursorHandlerAdapter<Item> {

   public ItemsCursorAdapter(Context context) {
      super(context, new ItemCursorHandler());
   }

   @Override
   public void bindView(View view, Context context, Cursor cursor) {
     /* Here we can fetch our pojo */ 
     Item item = getItem(cursor);

     /* Get the ViewHolder as usual and fill/set the views */
     ViewHolder holder = (ViewHolder) view.getTag();
     holder.xxxx.setYYY(....); 
   }

   @Override
   public View newView(Context context, Cursor cursor, ViewGroup parent) {
      View rowView = getLayoutInflater().inflate(R.layout.my_very_cool_layout, parent, false);

      ViewHolder holder = new ViewHolder();
      holder.xxxx = (YYYY)rowView.findViewById(R.id.yyyy);
      ...
      ...
      rowView.setTag(holder);

      return rowView;
   }

   static
   private class ViewHolder {
      YYYY  xxxx;
      ...
      ...
   };
}

在我们的片段或活动中,我们可以检索pojo:

ItemsCursorAdapter adapter = ...
Item value = adapter.getItem(position);
/* do whatever with the pojo */

通过这种方式,我不需要“剪切/复制或单一化”所有不同的cursorToPojo方法。

这是处理光标的正确方法吗?或者有一些可能的缺点?

你能指点我更合并的替代方案吗?

最诚挚的问候, LUS

1 个答案:

答案 0 :(得分:1)

如果你使用的是ContentProvider,那么就不要传递POJO,传递你的ContentProvider可以使用的Uri