在开发具有以下层次结构的布局时,我遇到了RealmRecyclerViewAdapter的问题:
>CoordinatorLayout
-->NestedScrollView
----> ConstraintLayout
------> RecyclerView
问题是,首次启动时,RecyclerView在将数据插入Realm后不会显示其子节点。
我的 fragment_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay"
app:elevation="0dp">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/AppTheme.PopupOverlay" >
<ImageView
android:id="@+id/mainLogo"
android:layout_width="96dp"
android:layout_height="48dp"
android:layout_gravity="center|top"
android:src="@drawable/ic_logo"
tools:ignore="ContentDescription"/>
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="184dp"
android:background="@color/colorLightGray"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<android.support.design.widget.TabLayout
android:id="@+id/tabDots"
android:layout_width="wrap_content"
android:layout_height="24dp"
android:layout_alignParentBottom="true"
app:layout_constraintBottom_toBottomOf="@+id/pager"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:tabBackground="@drawable/tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
app:tabPadding="2dp"
app:tabPaddingEnd="2dp"
tools:ignore="RtlSymmetry"/>
<Button
android:id="@+id/btnGuideOrder"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="1dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="1dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
style="@style/BtnBlock.Left"
android:text="@string/btn_guide_order"
app:layout_constraintEnd_toStartOf="@+id/btnGuidePay"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/pager"/>
<Button
android:id="@+id/btnGuidePay"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginRight="@dimen/spacing_normal"
android:layout_marginTop="16dp"
style="@style/BtnBlock.Right"
android:text="@string/btn_guide_pay"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/btnGuideOrder"
app:layout_constraintTop_toBottomOf="@+id/pager"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="32dp"
android:layout_marginTop="16dp"
android:background="@color/colorPrimary"
android:nestedScrollingEnabled="false"
android:paddingEnd="@dimen/spacing_product"
android:paddingLeft="@dimen/spacing_product"
android:paddingRight="@dimen/spacing_product"
android:paddingStart="@dimen/spacing_product"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnGuideOrder"
tools:ignore="UnusedAttribute"
tools:listitem="@layout/item_product"/>
</android.support.constraint.ConstraintLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
设置RecyclerView:
private fun setupRecycler() {
fetchProducts(RetrofitManager.homeCategoryId)
val products = realm.where(Product::class.java).findAll()
rvAdapter = RealmProductAdapter(products)
recycler.apply {
adapter = rvAdapter
layoutManager = GridLayoutManager(activity, 2)
setHasFixedSize(true)
}
}
获取数据:
private fun fetchProducts(categoryId: Int) {
val mContext = context ?: return
showProgress()
val disposable = RetrofitManager.createService(mContext, IctService::class.java)
.getCategoryProducts(authHeader(), categoryId)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
Log.d(_tag, "products, on Next")
realm.executeTransaction { _ ->
realm.copyToRealmOrUpdate(it)
}
hideProgress()
}, { error ->
Log.e(_tag, "error: $error, ${error.stackTrace}")
showErrorDialog { fetchProducts(categoryId) }
hideProgress()
})
compositeDisposable?.add(disposable)
}
到目前为止我尝试了什么?
我已经检查过RealmRecyclerViewAdapter在数据插入领域时在内部调用notifyItemRangeInserted,但它没有更新布局。仅在触发ChangeListener时手动调用适配器上的notifyDataSetChanged强制Recycler显示其内容。
products.addChangeListener { results, changeSet ->
Log.d(_tag, "setupRecycler, realmChangeListener, results: $results, set: $changeSet")
rvAdapter.notifyDataSetChanged()
}
将ConstraintLayout替换为另一个(LinearLayout)并不能解决问题。但是如果我将RecyclerView直接放在CoordinatorLayout中 - 它会在数据插入Realm后立即显示它的子节点。所以问题与RecyclerView只是NestedScrollView的子项有关。