【问题标题】:Get cursor by using Realm library使用 Realm 库获取光标
【发布时间】:2015-04-12 07:47:24
【问题描述】:

我正在为我的列表视图使用光标适配器。我打算使用内容解析器来获取光标。现在我改变主意给它一个学习 Realm 的机会。

我如何使用领域获得 "Cursor" 对象?顺便说一句,我也很感激给一些 sn-p 来排序光标。

谢谢。

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

}

【问题讨论】:

    标签: android android-contentprovider android-contentresolver realm


    【解决方案1】:

    来自Realm的Christian。 Realm 目前没有公开 Cursor,尽管这是我们想做的事情:https://github.com/realm/realm-java/issues/438

    如果您想将 RecyclerView 与 Realm 一起使用,我会推荐这篇博文以获取有关如何集成它们的建议:http://gradlewhy.ghost.io/realm-results-with-recyclerview/

    【讨论】:

    • 很高兴听到未来的更新 :) 我们可以在哪里试用快照构建?
    • 有关如何设置的信息,请参阅此:github.com/realm/realm-java/issues/936。最新 -SNAPSHOT 为 0.80.1
    • 它在 MavenCentral 中吗?还是快照服务器?
    • Doh,忘记发布链接了。它是 Bintrays 快照服务器。我已经更新了第一条评论。
    • 问题,为什么你遗漏了游标?在 Android 中使用领域时,这不是您的首要任务吗?不?我不知何故要求解释。
    【解决方案2】:

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

    但是,为了在 Cursor 界面上进行匹配,您可以从 Realm 中获取列表结果并从该数据中创建 MatrixCursor

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

    【讨论】:

      【解决方案3】:

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

      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 实例而不是使用realm.copyFromRealm(fn(realm))

      【讨论】:

        猜你喜欢
        • 2010-10-28
        • 2013-09-15
        • 2013-12-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-31
        • 2016-10-10
        相关资源
        最近更新 更多