34

我通常倾向于使用 POJO 来定义我的应用程序的模型层,例如 Article、Comment 等。

我正要在我的一个 ListViews 的适配器中实现一个 AlphabetIndexer。现在这个适配器接受一个文章集合,我通常从我的 SQLiteDatabase 的包装器中获得。

AlphabetIndexer 构造函数的签名如下:

public AlphabetIndexer (Cursor cursor, int sortedColumnIndex, CharSequence alphabet)

由于这不接受集合或类似的东西,只是一个游标,这让我想知道:也许我不应该为我的模型创建对象,而只使用从数据库返回的游标?

所以问题是,我想:我应该怎么做,用 POJO 的集合表示数据,或者只是在我的应用程序中使用游标?

有输入吗?

4

4 回答 4

13

我遇到了类似的问题。现在,我正在远离 POJO。Cursor但请注意,如果您愿意,可以为 POJO 集合创建自己的接口。

于 2010-03-30T13:33:24.753 回答
12

我喜欢创建游标支持的 POJO 类。Cursor 支持的 POJO 类有一个构造函数,它接受一个 Cursor 并提供以下好处:

  • 易于使用的 getter 可以返回正确的内容类型,比获取索引和必须记住数据库中的数据类型要好得多
  • 从其他 getter 计算结果的 getter 方法,就像 OO 编程应该如何
  • Getter 返回值可以是枚举!

这几个好处非常值得一些样板代码,由于用户工程师自己不访问游标列,因此避免了许多错误。我们仍然使用 CursorAdapter 类,但是 bindView 方法的第一行是从 Cursor 创建 Cursor-backed POJO,从那时起代码就很漂亮了。

下面是一个示例实现,用户工程师可以轻松地将不透明的光标转换为明确定义的用户对象,从那时起,只要后备光标没有关闭,它就可以像常规 POJO 一样传递和访问。SmartUserCursor 是我编写的一个特殊类,用于确保在访问游标之前记住并恢复游标位置,它还存储游标列索引,因此查找速度很快。

例子:

public class User {

    private final SmartUserCursor mCursor;

    public User(SmartUserCursor cursor, int position) {
        mCursor = new SmartUserCursor(cursor, position);
    }

    public long getUserId() {
        return mCursor.getLong(SmartUserCursor.Columns.userId);
    }

    public UserType getType() {
        return UserType.valueOf(mCursor.getString(SmartUserCursor.Columns.type));
    }

    public String getFirstName() {
        return mCursor.getString(SmartUserCursor.Columns.firstName);
    }

    public String getLastName() {
        return mCursor.getString(SmartUserCursor.Columns.lastName);
    }

    public final String getFullName() {
        return getFirstName() + " " + getLastName();
    }

    public static User newUserFromAdapter(BaseAdapter adapter, int position) {
        return new User((SmartUserCursor)adapter.getItem(position), position);
    }

    public static User newUserBlocking(Context context, long UserId) {
        Cursor cursor = context.getContentResolver().query(
                Users.CONTENT_URI_CLIENT,
                Users.DEFAULT_USER_PROJECTION,
                Users.Columns.USER_ID+"=?",
                new String[] {String.valueOf(UserId)},
                null
        );

        if (cursor == null || !cursor.moveToFirst()) {
            throw new RuntimeException("No User with id " + UserId + " exists");
        }

        return new User(new SmartUserCursor(cursor, Users.DEFAULT_USER_PROJECTION), -1);
    }

    public final void closeBackingCursor() {
        mCursor.close();
    }

}
于 2012-06-27T23:32:24.950 回答
9

一票实体对象 (POJO)。传递光标,尤其是传递到 UI 层,对我来说感觉很不对(无论 Android sdk 是否暗示这样做)。通常有几种方法可以填充你的 UI,我倾向于避免那些直接使用光标的方法。例如,为了填充我的自定义列表视图,我使用 SimpleAdapter 并让我的集合对象能够返回自己的表示作为List<? extends Map<String, ?>>SimpleAdapter 的构造函数。

我使用一种模式,其中每个表都由一个实体对象包装,并且有一个提供程序类来处理与该实体关联的我的 CRUD 操作。或者,如果我需要集合的扩展功能,我也将它们包装起来(即。EntityItems extends ArrayList<EntityItem>)提供者有一个基类,我将引用传递给 DbAdapter 类,该类在 db 周围进行繁重的工作。

除了个人喜好之外,最大的原因是我想将这种代码隐藏在尽可能远离我的 UI 的地方:

String something = cursor.getString(cursor.getColumnIndex(COLUMN_NAME_CONSTANT));

如果我在 UI 层中看到这种内联代码,我通常预计会看到更糟糕的情况潜伏在拐角处。也许我只是在企业界为大团队工作了太多时间,但我更喜欢可读性,除非存在合法的性能问题,或者如果它是一项足够小的任务,而表达能力只是企业过大的杀伤力。

于 2010-03-30T14:11:36.543 回答
2

答案是 4 岁。我认为现在我们有足够的 CPU 能力来处理更多的事情。我的想法是只使用 POJO 和 ArrayLists;并扩展 CursorLoader 以在后台将光标映射到 POJO 并将数组列表传递给活动;

除非您查询了数百行,但是,您这样做的频率与使用 POJO、getter 和 setter 的好处相比

于 2014-04-02T22:50:09.747 回答