Android 中 POJO 与游标

发布于 2024-08-27 02:15:41 字数 456 浏览 5 评论 0原文

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

我打算在我的一个 ListView 的适配器中实现一个 AlphabetIndexer。现在这个适配器接受一个文章集合,我通常从 SQLiteDatabase 的包装器中获取它。

AlphabetIndexer 构造函数的签名如下:

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

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

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

有什么意见吗?

I usually tend to define the model layer of my apps using POJO's, such as Article, Comment, etc.

I was about to implement an AlphabetIndexer in the adapter of one of my ListViews. Right now this adapter accepts a Collection of Articles, which I normally get from my wrapper around an SQLiteDatabase.

The signature of the AlphabetIndexer constructer is as follows:

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

Since this doesn't accept a Collection or something similar, just a Cursor, it got me wondering: maybe I shouldn't be creating objects for my model, and just use the Cursors returned from the database?

So the question is, I guess: what should I do, represent data with Collections of POJO's, or just work with Cursors throughout my app?

Any input?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

倒带 2024-09-03 02:15:41

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

I have run into similar issues. Right now, I am tending away from POJOs. Note, though, that you can create your own Cursor interface for a collection of POJOs, if you so choose.

涫野音 2024-09-03 02:15:41

我喜欢创建游标支持的 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();
    }

}

I like to create Cursor-backed POJO classes. A Cursor-backed POJO class has a constructor that takes a Cursor and provides the following benefits:

  • Easy to use getters that return the proper content type, much better
    than getting indexes and having to remember the type of data in the
    database
  • Getter methods that compute their results from other getters, just like how OO programming ought to be
  • Getter return values can be enums!

These few benefits are well worth some boilerplate code, many many bugs have been averted now that user-engineers aren't accessing cursor columns themselves. We still use the CursorAdapter class, but the first line in the bindView method is to create the Cursor-backed POJO from the Cursor and from then on the code is beautiful.

Below is an example implementation, it's a snap for user-engineers to turn an opaque cursor into clearly defined User object, from that point on it can be passed around and accessed just like a regular POJO so long as the backing cursor is not closed. The SmartUserCursor is a special class I wrote to ensure that the cursor position is remembered and restored before the cursor is accessed and it also stores the cursor column indexes so lookups are fast.

EXAMPLE:

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();
    }

}
梦行七里 2024-09-03 02:15:41

一票投给实体对象 (POJO)。传递光标,尤其是传递到 UI 层,对我来说感觉非常错误(无论 Android sdk 是否暗示这样做)。通常有多种方法来填充用户界面,我倾向于避免那些直接使用光标的方法。例如,为了填充我的自定义列表视图,我使用 SimpleAdapter 并使我的集合对象能够以 List> 用于 SimpleAdapter 的构造函数。

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

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

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

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

One vote for entity objects (POJOs). Passing cursors around, especially to the UI layer, feels so wrong to me (whether or not the Android sdk kinda implies doing it that way). There are usually several ways to populate your UI, and I tend to avoid those that directly use cursors. For example, to populate my custom list views, I use a SimpleAdapter and give my collection objects the ability to return a representation of themselves as a List<? extends Map<String, ?>> for the SimpleAdapter's constructor.

I use a pattern where each table is wrapped by an entity object and has a provider class that handles my CRUD operations associated with that entity. Optionally if I need extended functionality for the collections, I wrap them too (ie. EntityItems extends ArrayList<EntityItem>) The provider has a base class that I pass a reference to a DbAdapter class that does the heavy lifting around the db.

The biggest reason, other than personal preference, is that I want to hide this kind of code as far away from my UI as possible:

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

If I see that kind of code inline in the UI layer, I usually expect to see much worse lurking around the corner. Maybe I've just spent too much time in the corporate world working on big teams, but I favor readability unless there's a legit performance concern or if it's a small enough task where the expressiveness is just enterprisey overkill.

|煩躁 2024-09-03 02:15:41

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

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

Answers are 4 years old.
I think now we have enought CPU power to get away with more stuff. My idea would be to work only with POJOs and ArrayLists; and extending CursorLoader to map cursor to POJOs in the background and deliver arraylist to activity;

unless youre queries hundreds of rows but then, how often are you doing that vs. niceness of using POJOs, getters and setters

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文