POJO与Android中的游标

ben*_*nvd 33 android cursor pojo

我通常倾向于使用POJO定义我的应用程序的模型层,例如文章,评论等.

我准备在我的一个ListViews的适配器中实现AlphabetIndexer.现在这个适配器接受一个文章集合,我通常从我的包装器中获取SQLiteDatabase.

AlphabetIndexer构造函数的签名如下:

public AlphabetIndexer (Cursor cursor, int sortedColumnIndex, CharSequence alphabet)
Run Code Online (Sandbox Code Playgroud)

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

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

有什么输入?

Com*_*are 13

我遇到过类似的问题.现在,我正在逐渐远离POJO.但请注意,如果您愿意,可以Cursor为POJO集合创建自己的界面.

  • 我决定接受这个作为答案,因为我现在使用这种方法.具体来说,我在我的`SQLiteOpenHelper`中为它拥有的每个表创建了一个公共内部类.这些类包含一堆方法来防止我不得不乱用列名或数字.在ListViews中,性能差异很明显,只有几十个条目.另外,我似乎更喜欢`CursorAdapters`到`BaseAdapters`.我从你的书中获得了灵感(特别是Android Tutorials 2.9中的第102页),当我问这个问题时我没有回复,所以谢谢!:-) (4认同)

sat*_*ine 12

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

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

这些好处非常值得一些样板代码,由于用户工程师本身没有访问游标列,因此避免了许多错误.我们仍然使用CursorAdapter类,但bindView方法的第一行是从Cursor创建Cursor支持的POJO,然后在代码上很漂亮.

下面是一个示例实现,用户工程师可以轻松地将不透明光标转换为明确定义的User对象,从那一点开始就可以传递和访问,就像常规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();
    }

}
Run Code Online (Sandbox Code Playgroud)


Ric*_*ich 9

对实体对象(PO​​JO)投一票.传递游标,特别是UI层,对我来说感觉很不对劲(无论Android sdk是否意味着这样做).通常有几种方法来填充UI,我倾向于避免那些直接使用游标的方法.例如,要填充我的自定义列表视图,我使用SimpleAdapter并使我的集合对象能够返回自己的表示形式作为List<? extends Map<String, ?>>SimpleAdapter的构造函数.

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

除了个人偏好之外,最大的原因是我希望尽可能远离我的UI隐藏这种代码:

String something = cursor.getString(cursor.getColumnIndex(COLUMN_NAME_CONSTANT));
Run Code Online (Sandbox Code Playgroud)

如果我在UI层中看到内联代码,我通常希望看到更糟糕的潜伏在拐角处.也许我只是在企业界花了太多时间在大型团队工作,但我赞成可读性,除非有一个合理的性能问题,或者它是一个足够小的任务,表达性只是企业上的过度杀伤力.

  • "我使用SimpleAdapter并让我的集合对象能够将自己的表示形式返回给List <?extends Map <String,?>> for SimpleAdapter的构造函数" - 这涉及大量数据复制,占用CPU时间并产生垃圾.对于任何给定的应用程序,这可能或不重要. (4认同)
  • 嘿Rich.我也喜欢将UI与数据来源无关的方法,并且UI中的游标代码看起来也很难看,但我可以找到为什么需要它们的几个原因.首先,它们是将数据链接到ListViews之类的最有效方式.第二,要转换为集合,你必须线性迭代光标,O(n),每行创建一个你不会在光标中的对象,GC必须在某些时候收集它们,但最重要的是,您将整个集合加载到内存中.游标只保留当前行. (2认同)