Fix some issues with fragments managers (Home fragments) and lifecycle

This commit is contained in:
ganfra 2019-11-08 19:49:08 +01:00
parent 38da54119a
commit b6199b1f27
17 changed files with 75 additions and 63 deletions

View file

@ -41,7 +41,7 @@ fun <T : Fragment> VectorBaseFragment.replaceFragment(frameId: Int, fragmentClas
}
fun VectorBaseFragment.addFragmentToBackstack(frameId: Int, fragment: Fragment, tag: String? = null) {
parentFragmentManager.inTransaction { replace(frameId, fragment).addToBackStack(tag) }
parentFragmentManager.inTransaction { replace(frameId, fragment, tag).addToBackStack(tag) }
}
fun <T : Fragment> VectorBaseFragment.addFragmentToBackstack(frameId: Int, fragmentClass: Class<T>, params: Parcelable? = null, tag: String? = null) {
@ -50,8 +50,8 @@ fun <T : Fragment> VectorBaseFragment.addFragmentToBackstack(frameId: Int, fragm
}
}
fun VectorBaseFragment.addChildFragment(frameId: Int, fragment: Fragment) {
childFragmentManager.inTransaction { add(frameId, fragment) }
fun VectorBaseFragment.addChildFragment(frameId: Int, fragment: Fragment, tag: String? = null) {
childFragmentManager.inTransaction { add(frameId, fragment, tag) }
}
fun <T : Fragment> VectorBaseFragment.addChildFragment(frameId: Int, fragmentClass: Class<T>, params: Parcelable? = null, tag: String? = null) {
@ -60,8 +60,8 @@ fun <T : Fragment> VectorBaseFragment.addChildFragment(frameId: Int, fragmentCla
}
}
fun VectorBaseFragment.replaceChildFragment(frameId: Int, fragment: Fragment) {
childFragmentManager.inTransaction { replace(frameId, fragment) }
fun VectorBaseFragment.replaceChildFragment(frameId: Int, fragment: Fragment, tag: String? = null) {
childFragmentManager.inTransaction { replace(frameId, fragment, tag) }
}
fun <T : Fragment> VectorBaseFragment.replaceChildFragment(frameId: Int, fragmentClass: Class<T>, params: Parcelable? = null, tag: String? = null) {

View file

@ -114,11 +114,12 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), HasScreenInjector {
super.onDestroyView()
mUnBinder?.unbind()
mUnBinder = null
uiDisposables.clear()
}
override fun onDestroy() {
super.onDestroy()
uiDisposables.dispose()
super.onDestroy()
}
override fun injector(): ScreenComponent {
@ -181,7 +182,7 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), HasScreenInjector {
private val uiDisposables = CompositeDisposable()
protected fun Disposable.disposeOnDestroy(): Disposable {
protected fun Disposable.disposeOnDestroyView(): Disposable {
uiDisposables.add(this)
return this
}

View file

@ -34,14 +34,14 @@ interface MutableDataSource<T> : DataSource<T> {
*/
open class BehaviorDataSource<T>(private val defaultValue: T? = null) : MutableDataSource<T> {
private val storeRelay = createRelay()
private val behaviorRelay = createRelay()
override fun observe(): Observable<T> {
return storeRelay.hide().observeOn(Schedulers.computation())
return behaviorRelay.hide().observeOn(Schedulers.computation())
}
override fun post(value: T) {
storeRelay.accept(value)
behaviorRelay.accept(value)
}
private fun createRelay(): BehaviorRelay<T> {
@ -58,13 +58,13 @@ open class BehaviorDataSource<T>(private val defaultValue: T? = null) : MutableD
*/
open class PublishDataSource<T> : MutableDataSource<T> {
private val storeRelay = PublishRelay.create<T>()
private val publishRelay = PublishRelay.create<T>()
override fun observe(): Observable<T> {
return storeRelay.hide()
return publishRelay.hide()
}
override fun post(value: T) {
storeRelay.accept(value)
publishRelay.accept(value)
}
}

View file

@ -18,6 +18,7 @@ package im.vector.riotx.features.home
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import androidx.core.view.forEachIndexed
import androidx.lifecycle.Observer
import com.airbnb.mvrx.fragmentViewModel
@ -28,7 +29,8 @@ import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupState
import im.vector.matrix.android.api.session.group.model.GroupSummary
import im.vector.riotx.R
import im.vector.riotx.core.extensions.addChildFragmentToBackstack
import im.vector.riotx.core.extensions.inTransaction
import im.vector.riotx.core.extensions.replaceChildFragment
import im.vector.riotx.core.platform.ToolbarConfigurable
import im.vector.riotx.core.platform.VectorBaseFragment
import im.vector.riotx.core.ui.views.KeysBackupBanner
@ -59,9 +61,8 @@ class HomeDetailFragment @Inject constructor(
return R.layout.fragment_home_detail
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
sharedActionViewModel = activityViewModelProvider.get(HomeSharedActionViewModel::class.java)
setupBottomNavigationView()
@ -165,12 +166,15 @@ class HomeDetailFragment @Inject constructor(
private fun updateSelectedFragment(displayMode: RoomListFragment.DisplayMode) {
val fragmentTag = "FRAGMENT_TAG_${displayMode.name}"
val fragment = childFragmentManager.findFragmentByTag(fragmentTag)
if (fragment == null) {
val params = RoomListParams(displayMode)
addChildFragmentToBackstack(R.id.roomListContainer, RoomListFragment::class.java, params, fragmentTag)
} else {
addChildFragmentToBackstack(R.id.roomListContainer, fragment, fragmentTag)
val fragmentToShow = childFragmentManager.findFragmentByTag(fragmentTag)
childFragmentManager.inTransaction {
childFragmentManager.fragments.forEach { hide(it) }
if (fragmentToShow == null) {
val params = RoomListParams(displayMode)
add(R.id.roomListContainer, RoomListFragment::class.java, params.toMvRxBundle(), fragmentTag)
} else {
show(fragmentToShow)
}
}
}

View file

@ -17,6 +17,7 @@
package im.vector.riotx.features.home
import android.os.Bundle
import android.view.View
import im.vector.matrix.android.api.session.Session
import im.vector.riotx.R
import im.vector.riotx.core.extensions.observeK
@ -33,8 +34,8 @@ class HomeDrawerFragment @Inject constructor(
override fun getLayoutResId() = R.layout.fragment_home_drawer
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if (savedInstanceState == null) {
replaceChildFragment(R.id.homeDrawerGroupListContainer, GroupListFragment::class.java)
}
@ -55,4 +56,5 @@ class HomeDrawerFragment @Inject constructor(
navigator.openDebug(requireActivity())
}
}
}

View file

@ -18,6 +18,7 @@ package im.vector.riotx.features.home.createdirect
import android.content.Context
import android.os.Bundle
import android.view.View
import android.view.inputmethod.InputMethodManager
import com.airbnb.mvrx.activityViewModel
import com.airbnb.mvrx.withState
@ -40,8 +41,8 @@ class CreateDirectRoomDirectoryUsersFragment @Inject constructor(
private lateinit var sharedActionViewModel: CreateDirectRoomSharedActionViewModel
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
sharedActionViewModel = activityViewModelProvider.get(CreateDirectRoomSharedActionViewModel::class.java)
setupRecyclerView()
setupSearchByMatrixIdView()
@ -61,7 +62,7 @@ class CreateDirectRoomDirectoryUsersFragment @Inject constructor(
.subscribe {
viewModel.handle(CreateDirectRoomAction.SearchDirectoryUsers(it.toString()))
}
.disposeOnDestroy()
.disposeOnDestroyView()
createDirectRoomSearchById.requestFocus()
val imm = context?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
imm?.showSoftInput(createDirectRoomSearchById, InputMethodManager.SHOW_IMPLICIT)

View file

@ -21,6 +21,7 @@ package im.vector.riotx.features.home.createdirect
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.ScrollView
import androidx.core.view.size
import com.airbnb.mvrx.activityViewModel
@ -50,8 +51,8 @@ class CreateDirectRoomKnownUsersFragment @Inject constructor(
private val viewModel: CreateDirectRoomViewModel by activityViewModel()
private lateinit var sharedActionViewModel: CreateDirectRoomSharedActionViewModel
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
sharedActionViewModel = activityViewModelProvider.get(CreateDirectRoomSharedActionViewModel::class.java)
vectorBaseActivity.setSupportActionBar(createDirectRoomToolbar)
setupRecyclerView()
@ -113,7 +114,7 @@ class CreateDirectRoomKnownUsersFragment @Inject constructor(
}
viewModel.handle(action)
}
.disposeOnDestroy()
.disposeOnDestroyView()
createDirectRoomFilter.setupAsSearch()
createDirectRoomFilter.requestFocus()

View file

@ -17,6 +17,7 @@
package im.vector.riotx.features.home.group
import android.os.Bundle
import android.view.View
import com.airbnb.mvrx.Incomplete
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.fragmentViewModel
@ -40,8 +41,8 @@ class GroupListFragment @Inject constructor(
override fun getLayoutResId() = R.layout.fragment_group_list
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
sharedActionViewModel = activityViewModelProvider.get(HomeSharedActionViewModel::class.java)
groupController.callback = this
stateView.contentView = groupListEpoxyRecyclerView

View file

@ -203,8 +203,8 @@ class RoomDetailFragment @Inject constructor(
private var lockSendButton = false
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
sharedActionViewModel = activityViewModelProvider.get(MessageSharedActionViewModel::class.java)
attachmentsHelper = AttachmentsHelper.create(this, this).register()
keyboardStateUtils = KeyboardStateUtils(requireActivity())
@ -228,7 +228,7 @@ class RoomDetailFragment @Inject constructor(
.subscribe {
handleActions(it)
}
.disposeOnDestroy()
.disposeOnDestroyView()
roomDetailViewModel.navigateToEvent.observeEvent(this) {
val scrollPosition = timelineEventController.searchPositionOfEvent(it)
@ -273,7 +273,10 @@ class RoomDetailFragment @Inject constructor(
roomDetailViewModel.requestLiveData.observeEvent(this) {
displayRoomDetailActionResult(it)
}
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
if (savedInstanceState == null) {
when (val sharedData = roomDetailArgs.sharedData) {
is SharedData.Text -> roomDetailViewModel.handle(RoomDetailAction.SendMessage(sharedData.text, false))

View file

@ -20,6 +20,7 @@ import android.os.Bundle
import android.os.Parcelable
import android.view.Menu
import android.view.MenuItem
import android.view.View
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
@ -45,8 +46,10 @@ import im.vector.riotx.features.home.room.list.widget.FabMenuView
import im.vector.riotx.features.notifications.NotificationDrawerManager
import im.vector.riotx.features.share.SharedData
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.functions.Consumer
import kotlinx.android.parcel.Parcelize
import kotlinx.android.synthetic.main.fragment_room_list.*
import timber.log.Timber
import javax.inject.Inject
@Parcelize
@ -97,13 +100,13 @@ class RoomListFragment @Inject constructor(
super.onPrepareOptionsMenu(menu)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
sharedActionViewModel = activityViewModelProvider.get(RoomListQuickActionsSharedActionViewModel::class.java)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupCreateRoomButton()
setupRecyclerView()
roomListViewModel.subscribe { renderState(it) }
sharedActionViewModel = activityViewModelProvider.get(RoomListQuickActionsSharedActionViewModel::class.java)
roomListViewModel.subscribe { renderState(it) }
roomListViewModel.viewEvents
.observe()
.observeOn(AndroidSchedulers.mainThread())
@ -113,14 +116,14 @@ class RoomListFragment @Inject constructor(
is RoomListViewEvents.Failure -> showError(it)
}
}
.disposeOnDestroy()
.disposeOnDestroyView()
createChatFabMenu.listener = this
sharedActionViewModel
.observe()
.subscribe { handleQuickActions(it) }
.disposeOnDestroy()
.disposeOnDestroyView()
}
private fun openSelectedRoom(event: RoomListViewEvents.SelectRoom) {

View file

@ -62,7 +62,7 @@ class LoginFragment @Inject constructor() : VectorBaseFragment() {
viewModel.handle(LoginAction.UpdateHomeServer(homeServerField.text.toString()))
}
}
.disposeOnDestroy()
.disposeOnDestroyView()
homeServerField.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE) {
@ -107,7 +107,7 @@ class LoginFragment @Inject constructor() : VectorBaseFragment() {
}
)
.subscribeBy { authenticateButton.isEnabled = it }
.disposeOnDestroy()
.disposeOnDestroyView()
authenticateButton.setOnClickListener { authenticate() }
authenticateButtonSso.setOnClickListener { openSso() }

View file

@ -16,6 +16,7 @@
package im.vector.riotx.features.reactions
import android.os.Bundle
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import im.vector.riotx.R
import im.vector.riotx.core.platform.VectorBaseFragment
@ -27,8 +28,8 @@ class EmojiChooserFragment @Inject constructor() : VectorBaseFragment() {
private lateinit var viewModel: EmojiChooserViewModel
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = activityViewModelProvider.get(EmojiChooserViewModel::class.java)
viewModel.initWithContext(context!!)
(view as? RecyclerView)?.let {
@ -36,4 +37,5 @@ class EmojiChooserFragment @Inject constructor() : VectorBaseFragment() {
it.adapter?.notifyDataSetChanged()
}
}
}

View file

@ -16,6 +16,7 @@
package im.vector.riotx.features.reactions
import android.os.Bundle
import android.view.View
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
@ -37,9 +38,8 @@ class EmojiSearchResultFragment @Inject constructor(
var sharedViewModel: EmojiChooserViewModel? = null
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
sharedViewModel = activityViewModelProvider.get(EmojiChooserViewModel::class.java)
epoxyController.listener = object : ReactionClickListener {

View file

@ -67,7 +67,7 @@ class PublicRoomsFragment @Inject constructor(
.subscribeBy {
viewModel.handle(RoomDirectoryAction.FilterWith(it.toString()))
}
.disposeOnDestroy()
.disposeOnDestroyView()
publicRoomsCreateNewRoom.setOnClickListener {
sharedActionViewModel.post(RoomDirectorySharedAction.CreateRoom)

View file

@ -18,6 +18,7 @@ package im.vector.riotx.features.roomdirectory.createroom
import android.os.Bundle
import android.view.MenuItem
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.activityViewModel
@ -39,8 +40,8 @@ class CreateRoomFragment @Inject constructor(private val createRoomController: C
override fun getMenuRes() = R.menu.vector_room_creation
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
vectorBaseActivity.setSupportActionBar(createRoomToolbar)
sharedActionViewModel = activityViewModelProvider.get(RoomDirectorySharedActionViewModel::class.java)
setupRecyclerView()

View file

@ -55,6 +55,9 @@ class RoomDirectoryPickerFragment @Inject constructor(val roomDirectoryPickerVie
it.setDisplayShowHomeEnabled(true)
it.setDisplayHomeAsUpEnabled(true)
}
sharedActionViewModel = activityViewModelProvider.get(RoomDirectorySharedActionViewModel::class.java)
setupRecyclerView()
}
override fun getMenuRes() = R.menu.menu_directory_server_picker
@ -69,11 +72,6 @@ class RoomDirectoryPickerFragment @Inject constructor(val roomDirectoryPickerVie
return super.onOptionsItemSelected(item)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
sharedActionViewModel = activityViewModelProvider.get(RoomDirectorySharedActionViewModel::class.java)
setupRecyclerView()
}
private fun setupRecyclerView() {
val layoutManager = LinearLayoutManager(context)

View file

@ -45,16 +45,11 @@ class RoomPreviewNoPreviewFragment @Inject constructor(
private val roomPreviewViewModel: RoomPreviewViewModel by fragmentViewModel()
private val roomPreviewData: RoomPreviewData by args()
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setupToolbar(roomPreviewNoPreviewToolbar)
}
override fun getLayoutResId() = R.layout.fragment_room_preview_no_preview
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupToolbar(roomPreviewNoPreviewToolbar)
// Toolbar
avatarRenderer.render(roomPreviewData.avatarUrl, roomPreviewData.roomId, roomPreviewData.roomName, roomPreviewNoPreviewToolbarAvatar)
roomPreviewNoPreviewToolbarTitle.text = roomPreviewData.roomName