使用Realm库获取光标

时间:2015-04-12 07:47:25

标签: android android-contentprovider android-contentresolver realm

我正在使用游标适配器作为列表视图。我打算使用内容解析器来获取光标。现在我改变了主意,让它有机会学习Realm。

如何使用realm获取“Cursor”对象?顺便说一句,我也很乐意给几个片段来分类光标。

感谢。

final class Contact extends RealmObject {

private CharSequence mName;


public CharSequence getName() {
    return mName;
}

public void setName(CharSequence name) {
    this.mName = name;
}

}

final class ContactListAdapter extends CursorRecyclerViewAdapter<ContactListAdapter.ContactHolder> implements View.OnClickListener {

private OnContactClickListener mListener;


public ContactListAdapter(Context context, Cursor cursor) {
    super(context, cursor);
}

@Override
public ContactHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View itemView = getLayoutInflater().inflate(R.layout.cell_contact, parent, false);

    ContactHolder contactHolder = new ContactHolder(itemView);
    contactHolder.mContactPhotoImageView.setOnClickListener(this);

    return contactHolder;
}

@Override
public void onBindViewHolder(ContactHolder viewHolder, Cursor cursor) {
    viewHolder.mNameTextView.setText("Emre Akturk");

    int position = cursor.getPosition();
    viewHolder.mContactPhotoImageView.setImageResource(R.mipmap.ic_launcher);
    viewHolder.mContactPhotoImageView.setTag(position);
}

@Override
public int getItemCount() {
    return 5;
}

public void setOnContactClickListener(OnContactClickListener callback) {
    this.mListener = callback;
}

@Override
public void onClick(View v) {
    if (mListener == null) {
        return;
    }

    int position = (int) v.getTag();
    if (position == -1) {
        mListener.onContactCallClicked(v, getCursor(), position);
    } else {
        mListener.onContactAddClicked(v, position);
    }
}

public interface OnContactClickListener {
    void onContactCallClicked(View v, Cursor cursor, int position);

    void onContactAddClicked(View v, int position);
}

protected class ContactHolder extends RecyclerView.ViewHolder {
    private TextView mNameTextView;
    private CircleImageView mContactPhotoImageView;

    protected ContactHolder(View itemView) {
        super(itemView);
        mNameTextView = (TextView) itemView.findViewById(R.id.cell_contact_name_textview);
        mContactPhotoImageView = (CircleImageView) itemView.findViewById(R.id.cell_contact_photo_imageview);
    }
}

}

3 个答案:

答案 0 :(得分:7)

来自境界的克里斯蒂安。虽然我们想要做的事情,Realm目前还没有公开Cursor:https://github.com/realm/realm-java/issues/438

如果你想在Realm上使用RecyclerView,我会推荐这篇博文来获取有关如何整合它们的建议:http://gradlewhy.ghost.io/realm-results-with-recyclerview/

答案 1 :(得分:3)

目前,我认为Realm不支持ContentProvider架构。

但是,为了匹配Cursor接口,您可以从Realm获取列表结果并从此数据创建MatrixCursor

当然,这不是RAM性能的最佳解决方案。游标支持实际上是Realm上非常需要的功能。

答案 2 :(得分:0)

试试这个。它并不完美(我甚至不知道所有Cursor方法的功能......),但它对我有用:

SELECT
    user0_.ID_PRINCIPAL AS ID1_3_,
    user0_.VERSION      AS VERSION3_,
    user0_.NO_PRINCIPAL AS NO4_3_,
    user0_.IN_BLOQUEO   AS IN5_3_,
    user0_.IN_ACTIVO    AS IN6_3_
FROM JAAS_PRINCIPAL user0_
WHERE user0_.TT_DISCRIMINANTE = 'USER' AND user0_.NO_PRINCIPAL =?

然后你就可以使用它:

open class DetachedRealmCursor<T : RealmModel>(val clazz: Class<T>, fn: (Realm) -> RealmResults<T>) : Cursor { open val result: List<T> by lazy { val realm = Realm.getDefaultInstance() val list = realm.copyFromRealm(fn(realm)) //val list = fn(realm) realm.close() closed = false list } var current = 0 protected var notUri: Uri? = null protected var contencontObservable = ContentObservable() protected var datasetObservable = DataSetObservable() private val columnTypes: List<Int> private val columnNames: List<String> private var extras : Bundle = Bundle.EMPTY private var closed = true val FIELD_TYPE_REALMLIST = Cursor.FIELD_TYPE_BLOB+1 init { columnTypes = getFieldTypes() columnNames = getFieldNames() } private fun getFieldNames(): List<String> { return clazz.declaredFields?.map { it.name } ?: listOf("col1") } private fun getFieldTypes(): List<Int> { return clazz.declaredFields?.map { when (it.type) { String::class.java -> Cursor.FIELD_TYPE_STRING Float::class.java -> Cursor.FIELD_TYPE_FLOAT Int::class.java -> Cursor.FIELD_TYPE_INTEGER RealmList::class.java -> FIELD_TYPE_REALMLIST else -> Cursor.FIELD_TYPE_NULL } } ?: listOf(Cursor.FIELD_TYPE_STRING) } private fun getValueFromColumn(col: Int, pos: Int): Any? { val field = result[pos].javaClass.getDeclaredField(getColumnName(col)) field.isAccessible = true return field.get(result[pos]) } override fun moveToPosition(p0: Int): Boolean = if (p0 >= -1 && p0 <= result.size) { current = p0 true } else false override fun moveToFirst(): Boolean = if (result.isNotEmpty()) { current = 0 true } else false override fun move(p0: Int): Boolean = if (p0 >= -1 && p0 <= result.size) { current = p0 true } else { false } override fun moveToPrevious(): Boolean = if (current > -1) { current-- true } else false override fun moveToNext(): Boolean = if (current < result.size) { current++ true } else false override fun isBeforeFirst(): Boolean = current == -1 override fun moveToLast(): Boolean = if (result.isNotEmpty()) { current = result.size - 1 true } else false override fun isAfterLast(): Boolean = current >= result.size override fun getColumnIndexOrThrow(p0: String): Int { val found = columnNames.indexOf(p0) return if (found == -1) throw IllegalArgumentException() else found } override fun getColumnNames(): Array<String> = columnNames.toTypedArray() override fun getType(p0: Int): Int = columnTypes[p0] override fun getColumnName(p0: Int): String = columnNames[p0] override fun getColumnIndex(p0: String?): Int = columnNames.indexOf(p0) override fun getColumnCount(): Int = columnNames.size override fun getNotificationUri(): Uri? = notUri override fun deactivate() {} override fun requery(): Boolean = true override fun registerContentObserver(p0: ContentObserver) { // Register an observer that is called when changes happen to the content backing this cursor. // Typically the data set won't change until requery() is called. contencontObservable.registerObserver(p0) } override fun registerDataSetObserver(p0: DataSetObserver) { // Register an observer that is called when changes happen to the contents of the this // cursors data set, for example, when the data set is changed via requery(), deactivate(), or close(). datasetObservable.registerObserver(p0) } override fun unregisterContentObserver(p0: ContentObserver?) { if(!closed) { contencontObservable.unregisterObserver(p0) } } override fun unregisterDataSetObserver(p0: DataSetObserver?) { datasetObservable.unregisterObserver(p0) } override fun getWantsAllOnMoveCalls(): Boolean = false override fun getPosition(): Int = current override fun close() { closed = true contencontObservable.unregisterAll() datasetObservable.notifyInvalidated() } override fun isClosed() = closed override fun getCount(): Int = result.size override fun isFirst(): Boolean = current == 1 override fun isLast(): Boolean { return current == result.size - 1 } override fun isNull(p0: Int): Boolean = getValueFromColumn(p0, current) == null // poniższe można zamienić na getValueFromColumn override fun getLong(p0: Int): Long = getValueFromColumn(p0, current) as Long override fun getFloat(p0: Int): Float = getValueFromColumn(p0, current) as Float override fun getInt(p0: Int): Int = getValueFromColumn(p0, current) as Int override fun getBlob(p0: Int): ByteArray = getValueFromColumn(p0, current) as ByteArray override fun getShort(p0: Int): Short = getValueFromColumn(p0, current) as Short override fun getString(p0: Int): String = getValueFromColumn(p0, current) as String override fun getDouble(p0: Int): Double = getValueFromColumn(p0, current) as Double fun getList(p0: Int): RealmList<*> = getValueFromColumn(p0, current) as RealmList<*> override fun setNotificationUri(p0: ContentResolver?, p1: Uri?) { notUri = p1 } override fun copyStringToBuffer(p0: Int, p1: CharArrayBuffer?) {} override fun respond(extras: Bundle): Bundle = Bundle.EMPTY override fun getExtras(): Bundle = extras override fun setExtras(p0: Bundle) { extras = p0 } }

当然,如果您在同一个主题上完成所有工作,则可以直接使用val cursor = RealmCursor(RAlbum::class.java) { it.where(RAlbum::class.java).distinct("sTitle") }个实例,而不是realm