我做了很多使用SQLite的应用程序,而且经常无法设计数据库,因为我必须使用客户定义的Schema。
显然:-用户体验/用户界面设计师并不关心基础数据......她/他必须很酷!
所以我,不经常使用大量INNER JOIN
,LEFT JOIN
和非常大的SQL查询(但由于ContentProviders和Services的强大功能,这不是一个大问题。)< / p>
让我烦恼的是用于处理来自所有适配器.getItem(position)
的不同Cursor的“剪切/粘贴”(或静态最终)代码。
所以我想到了一种让事情更加清洁的方法,就像这样。
此接口的实现将Cursor转换为对象。
T
是输入Cursor将转换为的目标类型。
public interface CursorHandler<T> {
T handle(Cursor cu)
}
创建一个自定义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
答案 0 :(得分:1)
如果你使用的是ContentProvider,那么就不要传递POJO,传递你的ContentProvider可以使用的Uri