Fix various crashes

This commit is contained in:
Phillip Thelen 2019-08-16 09:13:14 +02:00
parent 66ca495763
commit 38f981558f
25 changed files with 69 additions and 300 deletions

View file

@ -149,7 +149,7 @@ android {
buildConfigField "String", "TESTING_LEVEL", "\"production\""
multiDexEnabled true
versionCode 2198
versionCode 2201
versionName "2.1"
}

View file

@ -10,6 +10,7 @@ import io.realm.RealmResults
class RealmTutorialLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm), TutorialLocalRepository {
override fun getTutorialStep(key: String): Flowable<TutorialStep> {
if (realm.isClosed) return Flowable.empty()
return realm.where(TutorialStep::class.java).equalTo("identifier", key)
.findAllAsync()
.asFlowable()
@ -30,6 +31,7 @@ class RealmTutorialLocalRepository(realm: Realm) : RealmBaseLocalRepository(real
}
override fun getTutorialSteps(keys: List<String>): Flowable<RealmResults<TutorialStep>> {
if (realm.isClosed) return Flowable.empty()
return realm.where(TutorialStep::class.java)
.`in`("identifier", keys.toTypedArray())
.findAll()

View file

@ -48,6 +48,7 @@ class RealmUserLocalRepository(realm: Realm) : RealmBaseLocalRepository(realm),
.filter { it.isLoaded }
override fun getUser(userID: String): Flowable<User> {
if (realm.isClosed) return Flowable.empty()
return realm.where(User::class.java)
.equalTo("id", userID)
.findAll()

View file

@ -1,202 +0,0 @@
package com.habitrpg.android.habitica.ui;
import android.content.Context;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import com.habitrpg.android.habitica.BuildConfig;
/**
* http://stackoverflow.com/a/29945693/1315039
*/
public class WrapContentRecyclerViewLayoutManager extends LinearLayoutManager {
private static final int CHILD_WIDTH = 0;
private static final int CHILD_HEIGHT = 1;
private static final int DEFAULT_CHILD_SIZE = 100;
private final int[] childDimensions = new int[2];
private int childSize = DEFAULT_CHILD_SIZE;
private boolean hasChildSize;
@SuppressWarnings("UnusedDeclaration")
public WrapContentRecyclerViewLayoutManager(Context context) {
super(context);
}
@SuppressWarnings("UnusedDeclaration")
public WrapContentRecyclerViewLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
public static int makeUnspecifiedSpec() {
return View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
}
@Override
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) {
final int widthMode = View.MeasureSpec.getMode(widthSpec);
final int heightMode = View.MeasureSpec.getMode(heightSpec);
final int widthSize = View.MeasureSpec.getSize(widthSpec);
final int heightSize = View.MeasureSpec.getSize(heightSpec);
final boolean exactWidth = widthMode == View.MeasureSpec.EXACTLY;
final boolean exactHeight = heightMode == View.MeasureSpec.EXACTLY;
final int unspecified = makeUnspecifiedSpec();
if (exactWidth && exactHeight) {
// in case of exact calculations for both dimensions let's use default "onMeasure" implementation
super.onMeasure(recycler, state, widthSpec, heightSpec);
return;
}
final boolean vertical = getOrientation() == VERTICAL;
initChildDimensions(widthSize, heightSize, vertical);
int width = 0;
int height = 0;
// it's possible to get scrap views in recycler which are bound to old (invalid) adapter entities. This
// happens because their invalidation happens after "onMeasure" method. As a workaround let's clear the
// recycler now (it should not cause any performance issues while scrolling as "onMeasure" is never
// called whiles scrolling)
recycler.clear();
final int stateItemCount = state.getItemCount();
final int adapterItemCount = getItemCount();
// adapter always contains actual data while state might contain old data (f.e. data before the animation is
// done). As we want to measure the view with actual data we must use data from the adapter and not from the
// state
for (int i = 0; i < adapterItemCount; i++) {
if (vertical) {
if (!hasChildSize) {
if (i < stateItemCount) {
// we should not exceed state count, otherwise we'll get IndexOutOfBoundsException. For such items
// we will use previously calculated dimensions
measureChild(recycler, i, widthSpec, unspecified, childDimensions);
} else {
logMeasureWarning(i);
}
}
height += childDimensions[CHILD_HEIGHT];
if (i == 0) {
width = childDimensions[CHILD_WIDTH];
}
} else {
if (!hasChildSize) {
if (i < stateItemCount) {
// we should not exceed state count, otherwise we'll get IndexOutOfBoundsException. For such items
// we will use previously calculated dimensions
measureChild(recycler, i, unspecified, heightSpec, childDimensions);
} else {
logMeasureWarning(i);
}
}
width += childDimensions[CHILD_WIDTH];
if (i == 0) {
height = childDimensions[CHILD_HEIGHT];
}
}
}
// we really should wrap the contents of the view, let's do it
if (exactWidth) {
width = widthSize;
} else {
width += getPaddingLeft() + getPaddingRight();
}
if (exactHeight) {
height = heightSize;
} else {
height += getPaddingTop() + getPaddingBottom();
}
setMeasuredDimension(width, height);
}
private void logMeasureWarning(int child) {
if (BuildConfig.DEBUG) {
Log.w("LinearLayoutManager", "Can't measure child #" + child + ", previously used dimensions will be reused." +
"To remove this message either use #setChildSize() method or don't run RecyclerView animations");
}
}
private void initChildDimensions(int width, int height, boolean vertical) {
if (childDimensions[CHILD_WIDTH] != 0 || childDimensions[CHILD_HEIGHT] != 0) {
// already initialized, skipping
return;
}
if (vertical) {
childDimensions[CHILD_WIDTH] = width;
childDimensions[CHILD_HEIGHT] = childSize;
} else {
childDimensions[CHILD_WIDTH] = childSize;
childDimensions[CHILD_HEIGHT] = height;
}
}
@Override
public void setOrientation(int orientation) {
// might be called before the constructor of this class is called
//noinspection ConstantConditions
if (childDimensions != null) {
if (getOrientation() != orientation) {
childDimensions[CHILD_WIDTH] = 0;
childDimensions[CHILD_HEIGHT] = 0;
}
}
super.setOrientation(orientation);
}
public void clearChildSize() {
hasChildSize = false;
setChildSize(DEFAULT_CHILD_SIZE);
}
public void setChildSize(int childSize) {
hasChildSize = true;
if (this.childSize != childSize) {
this.childSize = childSize;
requestLayout();
}
}
private void measureChild(RecyclerView.Recycler recycler, int position, int widthSpec, int heightSpec, int[] dimensions) {
final View child;
try {
child = recycler.getViewForPosition(position);
} catch (IndexOutOfBoundsException e) {
return;
}
final RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) child.getLayoutParams();
final int hPadding = getPaddingLeft() + getPaddingRight();
final int vPadding = getPaddingTop() + getPaddingBottom();
final int hMargin = p.leftMargin + p.rightMargin;
final int vMargin = p.topMargin + p.bottomMargin;
final int hDecoration = getRightDecorationWidth(child) + getLeftDecorationWidth(child);
final int vDecoration = getTopDecorationHeight(child) + getBottomDecorationHeight(child);
final int childWidthSpec = getChildMeasureSpec(widthSpec, hPadding + hMargin + hDecoration, p.width, canScrollHorizontally());
final int childHeightSpec = getChildMeasureSpec(heightSpec, vPadding + vMargin + vDecoration, p.height, canScrollVertically());
child.measure(childWidthSpec, childHeightSpec);
dimensions[CHILD_WIDTH] = getDecoratedMeasuredWidth(child) + p.leftMargin + p.rightMargin;
dimensions[CHILD_HEIGHT] = getDecoratedMeasuredHeight(child) + p.bottomMargin + p.topMargin;
recycler.recycleView(child);
}
}

View file

@ -94,6 +94,7 @@ class GroupInviteActivity : BaseActivity() {
private fun createResultIntent(): Intent {
val intent = Intent()
if (fragments.size == 0) return intent
val fragment = fragments[viewPager.currentItem]
if (viewPager.currentItem == 1) {
intent.putExtra(IS_EMAIL_KEY, true)

View file

@ -212,7 +212,7 @@ open class MainActivity : BaseActivity(), TutorialView.OnTutorialReaction {
val navigationController = findNavController(R.id.nav_host_fragment)
navigationController.addOnDestinationChangedListener { _, destination, _ ->
if (destination.label.isNullOrEmpty()) {
if (destination.label.isNullOrEmpty() && user?.isValid == true) {
toolbarTitleTextView.text = user?.profile?.name
} else if (user?.profile != null) {
toolbarTitleTextView.text = destination.label

View file

@ -46,12 +46,12 @@ class SkillMemberActivity : BaseActivity() {
resultIntent.putExtra("member_id", userId)
setResult(Activity.RESULT_OK, resultIntent)
finish()
}, RxErrorHandler.handleEmptyError())
}, RxErrorHandler.handleEmptyError())?.let { compositeSubscription.add(it) }
recyclerView.adapter = viewAdapter
userRepository.getUser()
compositeSubscription.add(userRepository.getUser()
.firstElement()
.flatMap { user -> socialRepository.getGroupMembers(user.party?.id ?: "").firstElement() }
.subscribe(Consumer { viewAdapter?.updateData(it) }, RxErrorHandler.handleEmptyError())
.subscribe(Consumer { viewAdapter?.updateData(it) }, RxErrorHandler.handleEmptyError()))
}
}

View file

@ -394,6 +394,8 @@ class TaskFormActivity : BaseActivity() {
thisTask = Task()
thisTask.type = taskType
thisTask.dateCreated = Date()
} else {
if (!thisTask.isValid) return
}
thisTask.text = textEditText.text.toString()
thisTask.notes = notesEditText.text.toString()
@ -405,8 +407,8 @@ class TaskFormActivity : BaseActivity() {
thisTask.up = habitScoringButtons.isPositive
thisTask.down = habitScoringButtons.isNegative
thisTask.frequency = habitResetStreakButtons.selectedResetOption.value
if (habitAdjustPositiveStreakView.text.isNotEmpty()) thisTask.counterUp = habitAdjustPositiveStreakView.text.toString().toInt()
if (habitAdjustNegativeStreakView.text.isNotEmpty()) thisTask.counterDown = habitAdjustNegativeStreakView.text.toString().toInt()
if (habitAdjustPositiveStreakView.text.isNotEmpty()) thisTask.counterUp = habitAdjustPositiveStreakView.text.toString().toIntCatchOverflow()
if (habitAdjustNegativeStreakView.text.isNotEmpty()) thisTask.counterDown = habitAdjustNegativeStreakView.text.toString().toIntCatchOverflow()
} else if (taskType == Task.TYPE_DAILY) {
thisTask.startDate = taskSchedulingControls.startDate
thisTask.everyX = taskSchedulingControls.everyX
@ -414,7 +416,7 @@ class TaskFormActivity : BaseActivity() {
thisTask.repeat = taskSchedulingControls.weeklyRepeat
thisTask.setDaysOfMonth(taskSchedulingControls.daysOfMonth)
thisTask.setWeeksOfMonth(taskSchedulingControls.weeksOfMonth)
if (habitAdjustPositiveStreakView.text.isNotEmpty()) thisTask.streak = habitAdjustPositiveStreakView.text.toString().toInt()
if (habitAdjustPositiveStreakView.text.isNotEmpty()) thisTask.streak = habitAdjustPositiveStreakView.text.toString().toIntCatchOverflow()
} else if (taskType == Task.TYPE_TODO) {
thisTask.dueDate = taskSchedulingControls.dueDate
} else if (taskType == Task.TYPE_REWARD) {
@ -491,4 +493,12 @@ class TaskFormActivity : BaseActivity() {
// in order to disable the event handler in MainActivity
const val SET_IGNORE_FLAG = "ignoreFlag"
}
}
}
private fun String.toIntCatchOverflow(): Int? {
return try {
toInt()
} catch (e: NumberFormatException) {
0
}
}

View file

@ -35,7 +35,7 @@ class ChallengesListViewAdapter(data: OrderedRealmCollection<Challenge>?, autoUp
data?.get(position)?.let { challenge ->
holder.bind(challenge, challengeMemberships?.first { challenge.id == it.challengeID } != null)
holder.itemView.setOnClickListener {
if (challenge.isManaged) {
if (challenge.isManaged && challenge.isValid) {
challenge.id?.let {
openChallengeFragmentEvents.onNext(it)
}

View file

@ -29,7 +29,6 @@ class AchievementsFragment: BaseMainFragment(), SwipeRefreshLayout.OnRefreshList
private var menuID: Int = 0
private lateinit var adapter: AchievementsAdapter
private val layoutManager = GridLayoutManager(activity, 2)
private var useGridLayout = false
set(value) {
field = value
@ -69,6 +68,7 @@ class AchievementsFragment: BaseMainFragment(), SwipeRefreshLayout.OnRefreshList
resetViews()
val layoutManager = GridLayoutManager(activity, 2)
recyclerView.layoutManager = layoutManager
recyclerView.adapter = adapter
adapter.useGridLayout = useGridLayout

View file

@ -61,7 +61,7 @@ class SubscriptionFragment : BaseFragment(), GemPurchaseActivity.CheckoutFragmen
private val subscribeListItem3Description: TextView? by bindView(R.id.subscribe_listitem3_description)
private val subscribeListItem4Description: TextView? by bindView(R.id.subscribe_listitem4_description)
private val loadingIndicator: ProgressBar? by bindView(R.id.loadingIndicator)
private val loadingIndicator: ProgressBar? by bindOptionalView(R.id.loadingIndicator)
private val subscriptionOptions: View? by bindView(R.id.subscriptionOptions)
private val subscription1MonthView: SubscriptionOptionView? by bindView(R.id.subscription1month)

View file

@ -81,19 +81,17 @@ class AvatarCustomizationFragment : BaseMainFragment() {
}
setGridSpanCount(view.width)
if (recyclerView.layoutManager == null) {
layoutManager = GridLayoutManager(activity, 2)
layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
return if (adapter.getItemViewType(position) == 0) {
layoutManager.spanCount
} else {
1
}
val layoutManager = GridLayoutManager(activity, 2)
layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
return if (adapter.getItemViewType(position) == 0) {
layoutManager.spanCount
} else {
1
}
}
recyclerView.layoutManager = layoutManager
}
recyclerView.layoutManager = layoutManager
recyclerView.addItemDecoration(MarginDecoration(context))
recyclerView.adapter = adapter

View file

@ -94,7 +94,7 @@ class AvatarOverviewFragment : BaseMainFragment(), AdapterView.OnItemSelectedLis
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
val newSize: String = if (position == 0) "slim" else "broad"
if (this.user != null && this.user?.preferences?.size != newSize) {
if (this.user?.isValid == true && this.user?.preferences?.size != newSize) {
compositeSubscription.add(userRepository.updateUser(user, "preferences.size", newSize)
.subscribe(Consumer { }, RxErrorHandler.handleEmptyError()))
}

View file

@ -74,13 +74,9 @@ class ItemRecyclerFragment : BaseFragment() {
val context = activity
layoutManager = recyclerView?.layoutManager as? androidx.recyclerview.widget.LinearLayoutManager
layoutManager = androidx.recyclerview.widget.LinearLayoutManager(context)
if (layoutManager == null) {
layoutManager = androidx.recyclerview.widget.LinearLayoutManager(context)
recyclerView?.layoutManager = layoutManager
}
recyclerView?.layoutManager = layoutManager
adapter = recyclerView?.adapter as? ItemRecyclerAdapter
if (adapter == null) {

View file

@ -56,7 +56,6 @@ class AvatarSetupFragment : BaseFragment() {
private val randomizeButton: Button? by bindOptionalView(R.id.randomize_button)
internal var adapter: CustomizationSetupAdapter? = null
internal var layoutManager: LinearLayoutManager = LinearLayoutManager(activity)
private var user: User? = null
private var subcategories: List<String> = emptyList()
@ -81,9 +80,9 @@ class AvatarSetupFragment : BaseFragment() {
adapter?.equipGearEvents?.flatMap { inventoryRepository.equip(user, "equipped", it) }?.subscribeWithErrorHandler(Consumer {})?.let { compositeSubscription.add(it) }
this.adapter?.user = this.user
this.layoutManager = LinearLayoutManager(activity)
this.layoutManager.orientation = LinearLayoutManager.HORIZONTAL
this.customizationList?.layoutManager = this.layoutManager
val layoutManager = LinearLayoutManager(activity)
layoutManager.orientation = LinearLayoutManager.HORIZONTAL
this.customizationList?.layoutManager = layoutManager
this.customizationList?.adapter = this.adapter

View file

@ -1,29 +1,26 @@
package com.habitrpg.android.habitica.ui.fragments.skills
import android.os.Bundle
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.habitrpg.android.habitica.R
import com.habitrpg.android.habitica.components.UserComponent
import com.habitrpg.android.habitica.data.TaskRepository
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.helpers.RxErrorHandler
import com.habitrpg.android.habitica.models.tasks.Task
import com.habitrpg.android.habitica.modules.AppModule
import com.habitrpg.android.habitica.ui.adapter.SkillTasksRecyclerViewAdapter
import com.habitrpg.android.habitica.ui.fragments.BaseFragment
import com.habitrpg.android.habitica.ui.helpers.SafeDefaultItemAnimator
import javax.inject.Inject
import javax.inject.Named
import com.habitrpg.android.habitica.extensions.inflate
import com.habitrpg.android.habitica.ui.helpers.bindView
import io.reactivex.Flowable
import io.reactivex.functions.Consumer
import javax.inject.Inject
import javax.inject.Named
class SkillTasksRecyclerViewFragment : BaseFragment() {
@Inject
@ -55,13 +52,8 @@ class SkillTasksRecyclerViewFragment : BaseFragment() {
compositeSubscription.add(taskRepository.getTasks(taskType ?: "", userId).firstElement().subscribe(Consumer { tasks -> adapter.updateData(tasks) }, RxErrorHandler.handleEmptyError()))
recyclerView?.adapter = adapter
layoutManager = recyclerView?.layoutManager as? LinearLayoutManager
if (layoutManager == null) {
layoutManager = LinearLayoutManager(context)
recyclerView?.layoutManager = layoutManager
}
val layoutManager = LinearLayoutManager(context)
recyclerView?.layoutManager = layoutManager
recyclerView?.itemAnimator = SafeDefaultItemAnimator()
}
}

View file

@ -44,7 +44,6 @@ class ChatFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener {
@Inject
lateinit var configManager: AppConfigManager
internal var layoutManager: LinearLayoutManager? = null
private var chatAdapter: ChatRecyclerViewAdapter? = null
private var navigatedOnceToFragment = false
private var isScrolledToTop = true
@ -64,12 +63,8 @@ class ChatFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener {
super.onViewCreated(view, savedInstanceState)
refreshLayout.setOnRefreshListener(this)
layoutManager = recyclerView.layoutManager as? LinearLayoutManager
if (layoutManager == null) {
layoutManager = LinearLayoutManager(context)
recyclerView.layoutManager = layoutManager
}
val layoutManager = LinearLayoutManager(context)
recyclerView.layoutManager = layoutManager
chatAdapter = ChatRecyclerViewAdapter(null, true, null, true)
chatAdapter?.let {adapter ->

View file

@ -55,7 +55,6 @@ class ChatListFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener {
chatBarView.autocompleteContext = value
}
}
internal var layoutManager: LinearLayoutManager? = null
internal var groupId: String? = null
private var user: User? = null
private var userId: String? = null
@ -111,12 +110,8 @@ class ChatListFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener {
super.onViewCreated(view, savedInstanceState)
refreshLayout.setOnRefreshListener(this)
layoutManager = recyclerView.layoutManager as? LinearLayoutManager
if (layoutManager == null) {
layoutManager = LinearLayoutManager(context)
recyclerView.layoutManager = layoutManager
}
val layoutManager = LinearLayoutManager(context)
recyclerView.layoutManager = layoutManager
chatAdapter = ChatRecyclerViewAdapter(null, true, user, true)
chatAdapter?.let {adapter ->

View file

@ -54,7 +54,7 @@ class PartyDetailFragment : BaseFragment() {
private val questDetailButton: ViewGroup? by bindView(R.id.quest_detail_button)
private val questScrollImageView: SimpleDraweeView? by bindView(R.id.quest_scroll_image_view)
private val questTitleView: TextView? by bindOptionalView(R.id.quest_title_view)
private val questParticipationView: TextView? by bindView(R.id.quest_participation_view)
private val questParticipationView: TextView? by bindOptionalView(R.id.quest_participation_view)
private val questImageWrapper: ViewGroup? by bindView(R.id.quest_image_wrapper)
private val questImageView: SimpleDraweeView? by bindView(R.id.quest_image_view)
private val questParticipantResponseWrapper: ViewGroup? by bindView(R.id.quest_participant_response_wrapper)

View file

@ -255,7 +255,7 @@ class PartyFragment : BaseMainFragment() {
}
override fun getCount(): Int {
return if (user?.hasParty() != true) {
return if (user?.isValid != true || user?.hasParty() != true) {
1
} else {
2

View file

@ -63,8 +63,9 @@ class RewardsRecyclerviewFragment : TaskRecyclerViewFragment() {
}, RxErrorHandler.handleEmptyError())?.let { compositeSubscription.add(it) }
}
override fun getLayoutManager(context: Context?): LinearLayoutManager =
GridLayoutManager(context, 4)
override fun getLayoutManager(context: Context?): LinearLayoutManager {
return GridLayoutManager(context, 4)
}
override fun onRefresh() {
refreshLayout.isRefreshing = true

View file

@ -204,7 +204,9 @@ open class TaskRecyclerViewFragment : BaseFragment(), androidx.swiperefreshlayou
return inflater.inflate(R.layout.fragment_refresh_recyclerview, container, false)
}
protected open fun getLayoutManager(context: Context?): androidx.recyclerview.widget.LinearLayoutManager = androidx.recyclerview.widget.LinearLayoutManager(context)
protected open fun getLayoutManager(context: Context?): androidx.recyclerview.widget.LinearLayoutManager {
return androidx.recyclerview.widget.LinearLayoutManager(context)
}
override fun onDestroy() {
userRepository.close()
@ -222,13 +224,9 @@ open class TaskRecyclerViewFragment : BaseFragment(), androidx.swiperefreshlayou
recyclerView.adapter = recyclerAdapter as? androidx.recyclerview.widget.RecyclerView.Adapter<*>
recyclerAdapter?.filter()
layoutManager = recyclerView.layoutManager
layoutManager = getLayoutManager(context)
recyclerView.layoutManager = layoutManager
if (layoutManager == null) {
layoutManager = getLayoutManager(context)
recyclerView.layoutManager = layoutManager
}
if (recyclerView.adapter == null) {
this.setInnerAdapter()
}

View file

@ -49,7 +49,13 @@ class TasksFragment : BaseMainFragment() {
private val activeFragment: TaskRecyclerViewFragment?
get() {
return viewFragmentsDictionary?.get(viewPager?.currentItem) ?: (childFragmentManager.findFragmentByTag("android:switcher:" + R.id.viewPager + ":" + viewPager?.currentItem) as? TaskRecyclerViewFragment)
var fragment = viewFragmentsDictionary?.get(viewPager?.currentItem)
if (fragment == null) {
if (isAdded) {
fragment = (childFragmentManager.findFragmentByTag("android:switcher:" + R.id.viewPager + ":" + viewPager?.currentItem) as? TaskRecyclerViewFragment)
}
}
return fragment
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,

View file

@ -36,7 +36,7 @@ class RecyclerViewEmptySupport : RecyclerView {
}
}
override fun setAdapter(adapter: RecyclerView.Adapter<*>?) {
override fun setAdapter(adapter: Adapter<*>?) {
val oldAdapter = getAdapter()
oldAdapter?.unregisterAdapterDataObserver(observer)
super.setAdapter(adapter)

View file

@ -1,23 +0,0 @@
package com.habitrpg.android.habitica.ui.views
import android.content.Context
import android.util.AttributeSet
import android.widget.LinearLayout
import com.habitrpg.android.habitica.ui.helpers.NavbarUtils
open class PaddedLinearLayout : LinearLayout {
private var navBarAccountedHeightCalculated = false
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle)
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val navbarHeight = NavbarUtils.getNavbarHeight(context)
val params = layoutParams as? MarginLayoutParams
params?.setMargins(0, 0, 0, navbarHeight)
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}
}