Fix crash reported by the PlayStore.

NullPointerException: at im.vector.riotx.features.home.room.detail.RoomDetailFragment.updateJumpToReadMarkerViewVisibility (RoomDetailFragment.kt:524)
Also properly cleanup model build listener
This commit is contained in:
Benoit Marty 2019-12-06 12:00:29 +01:00
parent 8b1701e537
commit c714266a81
2 changed files with 39 additions and 27 deletions

View file

@ -46,6 +46,7 @@ import androidx.recyclerview.widget.RecyclerView
import butterknife.BindView
import com.airbnb.epoxy.EpoxyModel
import com.airbnb.epoxy.EpoxyVisibilityTracker
import com.airbnb.epoxy.OnModelBuildFinishedListener
import com.airbnb.mvrx.*
import com.github.piasy.biv.BigImageViewer
import com.github.piasy.biv.loader.ImageLoader
@ -193,6 +194,8 @@ class RoomDetailFragment @Inject constructor(
private lateinit var sharedActionViewModel: MessageSharedActionViewModel
private lateinit var layoutManager: LinearLayoutManager
private lateinit var modelBuildListener: OnModelBuildFinishedListener
private lateinit var attachmentsHelper: AttachmentsHelper
private lateinit var keyboardStateUtils: KeyboardStateUtils
@ -286,8 +289,9 @@ class RoomDetailFragment @Inject constructor(
}
override fun onDestroyView() {
super.onDestroyView()
timelineEventController.removeModelBuildListener(modelBuildListener)
recyclerView.adapter = null
super.onDestroyView()
}
override fun onDestroy() {
@ -470,13 +474,14 @@ class RoomDetailFragment @Inject constructor(
recyclerView.layoutManager = layoutManager
recyclerView.itemAnimator = null
recyclerView.setHasFixedSize(true)
timelineEventController.addModelBuildListener {
modelBuildListener = OnModelBuildFinishedListener {
it.dispatchTo(stateRestorer)
it.dispatchTo(scrollOnNewMessageCallback)
it.dispatchTo(scrollOnHighlightedEventCallback)
updateJumpToReadMarkerViewVisibility()
updateJumpToBottomViewVisibility()
}
timelineEventController.addModelBuildListener { modelBuildListener }
recyclerView.adapter = timelineEventController.adapter
recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
@ -521,37 +526,41 @@ class RoomDetailFragment @Inject constructor(
}
}
private fun updateJumpToReadMarkerViewVisibility() = jumpToReadMarkerView.post {
withState(roomDetailViewModel) {
val showJumpToUnreadBanner = when (it.unreadState) {
UnreadState.Unknown,
UnreadState.HasNoUnread -> false
is UnreadState.ReadMarkerNotLoaded -> true
is UnreadState.HasUnread -> {
if (it.canShowJumpToReadMarker) {
val lastVisibleItem = layoutManager.findLastVisibleItemPosition()
val positionOfReadMarker = timelineEventController.getPositionOfReadMarker()
if (positionOfReadMarker == null) {
false
private fun updateJumpToReadMarkerViewVisibility() {
jumpToReadMarkerView?.post {
withState(roomDetailViewModel) {
val showJumpToUnreadBanner = when (it.unreadState) {
UnreadState.Unknown,
UnreadState.HasNoUnread -> false
is UnreadState.ReadMarkerNotLoaded -> true
is UnreadState.HasUnread -> {
if (it.canShowJumpToReadMarker) {
val lastVisibleItem = layoutManager.findLastVisibleItemPosition()
val positionOfReadMarker = timelineEventController.getPositionOfReadMarker()
if (positionOfReadMarker == null) {
false
} else {
positionOfReadMarker > lastVisibleItem
}
} else {
positionOfReadMarker > lastVisibleItem
false
}
} else {
false
}
}
jumpToReadMarkerView.isVisible = showJumpToUnreadBanner
}
jumpToReadMarkerView.isVisible = showJumpToUnreadBanner
}
}
private fun updateJumpToBottomViewVisibility() {
debouncer.debounce("jump_to_bottom_visibility", 250, Runnable {
Timber.v("First visible: ${layoutManager.findFirstCompletelyVisibleItemPosition()}")
if (layoutManager.findFirstVisibleItemPosition() != 0) {
jumpToBottomView.show()
} else {
jumpToBottomView.hide()
if (isAdded) {
Timber.v("First visible: ${layoutManager.findFirstCompletelyVisibleItemPosition()}")
if (layoutManager.findFirstVisibleItemPosition() != 0) {
jumpToBottomView.show()
} else {
jumpToBottomView.hide()
}
}
})
}

View file

@ -26,6 +26,7 @@ import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.airbnb.epoxy.OnModelBuildFinishedListener
import com.airbnb.mvrx.*
import com.google.android.material.snackbar.Snackbar
import im.vector.matrix.android.api.failure.Failure
@ -38,10 +39,9 @@ import im.vector.riotx.core.error.ErrorFormatter
import im.vector.riotx.core.platform.OnBackPressed
import im.vector.riotx.core.platform.StateView
import im.vector.riotx.core.platform.VectorBaseFragment
import im.vector.riotx.features.home.RoomListDisplayMode
import im.vector.riotx.features.home.room.list.actions.RoomListQuickActionsSharedAction
import im.vector.riotx.features.home.room.list.actions.RoomListQuickActionsBottomSheet
import im.vector.riotx.features.home.room.list.actions.RoomListQuickActionsSharedAction
import im.vector.riotx.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel
import im.vector.riotx.features.home.room.list.widget.FabMenuView
import im.vector.riotx.features.notifications.NotificationDrawerManager
@ -65,6 +65,7 @@ class RoomListFragment @Inject constructor(
) : VectorBaseFragment(), RoomSummaryController.Listener, OnBackPressed, FabMenuView.Listener {
private lateinit var modelBuildListener: OnModelBuildFinishedListener
private lateinit var sharedActionViewModel: RoomListQuickActionsSharedActionViewModel
private val roomListParams: RoomListParams by args()
private val roomListViewModel: RoomListViewModel by fragmentViewModel()
@ -118,8 +119,9 @@ class RoomListFragment @Inject constructor(
}
override fun onDestroyView() {
super.onDestroyView()
roomController.removeModelBuildListener(modelBuildListener)
roomListView.adapter = null
super.onDestroyView()
}
private fun openSelectedRoom(event: RoomListViewEvents.SelectRoom) {
@ -198,7 +200,8 @@ class RoomListFragment @Inject constructor(
roomListView.layoutManager = layoutManager
roomListView.itemAnimator = RoomListAnimator()
roomController.listener = this
roomController.addModelBuildListener { it.dispatchTo(stateRestorer) }
modelBuildListener = OnModelBuildFinishedListener { it.dispatchTo(stateRestorer) }
roomController.addModelBuildListener(modelBuildListener)
roomListView.adapter = roomController.adapter
stateView.contentView = roomListView
}