diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueFragment.kt index 52c0f1010..0732ff610 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueFragment.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueFragment.kt @@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.ui.catalogue import android.os.Bundle import android.support.v7.widget.GridLayoutManager -import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.SearchView import android.support.v7.widget.Toolbar import android.view.* @@ -24,6 +23,7 @@ import eu.kanade.tachiyomi.util.snack import eu.kanade.tachiyomi.util.toast import eu.kanade.tachiyomi.widget.EndlessGridScrollListener import eu.kanade.tachiyomi.widget.EndlessListScrollListener +import eu.kanade.tachiyomi.widget.NpaLinearLayoutManager import kotlinx.android.synthetic.main.fragment_catalogue.* import kotlinx.android.synthetic.main.toolbar.* import nucleus.factory.RequiresPresenter @@ -150,7 +150,7 @@ class CatalogueFragment : BaseRxFragment(), FlexibleViewHold catalogue_grid.adapter = adapter catalogue_grid.addOnScrollListener(gridScrollListener) - val llm = LinearLayoutManager(activity) + val llm = NpaLinearLayoutManager(activity) listScrollListener = EndlessListScrollListener(llm, { requestNextPage() }) catalogue_list.setHasFixedSize(true) catalogue_list.adapter = adapter diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueGridHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueGridHolder.kt index 7a41823fe..6b44f0387 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueGridHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/catalogue/CatalogueGridHolder.kt @@ -42,7 +42,7 @@ class CatalogueGridHolder(private val view: View, private val adapter: Catalogue * @param manga the manga to bind. */ fun setImage(manga: Manga) { - if (manga.thumbnail_url != null) { + if (!manga.thumbnail_url.isNullOrEmpty()) { val url = manga.thumbnail_url!! val headers = adapter.fragment.presenter.source.glideHeaders diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryActivity.kt index 162c5aa31..f86d1a5cd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryActivity.kt @@ -4,7 +4,6 @@ import android.content.Context import android.content.Intent import android.os.Bundle import android.support.v7.view.ActionMode -import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.RecyclerView import android.support.v7.widget.helper.ItemTouchHelper import android.view.Menu @@ -16,6 +15,7 @@ import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.ui.base.activity.BaseRxActivity import eu.kanade.tachiyomi.ui.base.adapter.FlexibleViewHolder import eu.kanade.tachiyomi.ui.base.adapter.OnStartDragListener +import eu.kanade.tachiyomi.widget.NpaLinearLayoutManager import kotlinx.android.synthetic.main.activity_edit_categories.* import kotlinx.android.synthetic.main.toolbar.* import nucleus.factory.RequiresPresenter @@ -70,7 +70,7 @@ class CategoryActivity : BaseRxActivity(), ActionMode.Callbac adapter = CategoryAdapter(this) // Create view and inject category items into view - recycler.layoutManager = LinearLayoutManager(this) + recycler.layoutManager = NpaLinearLayoutManager(this) recycler.setHasFixedSize(true) recycler.adapter = adapter diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadFragment.kt index a9ec45f0e..9212b83b6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadFragment.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadFragment.kt @@ -1,13 +1,13 @@ package eu.kanade.tachiyomi.ui.download import android.os.Bundle -import android.support.v7.widget.LinearLayoutManager import android.view.* import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.download.DownloadService import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment import eu.kanade.tachiyomi.ui.main.MainActivity +import eu.kanade.tachiyomi.widget.NpaLinearLayoutManager import kotlinx.android.synthetic.main.fragment_download_queue.* import nucleus.factory.RequiresPresenter import rx.Subscription @@ -82,7 +82,7 @@ class DownloadFragment : BaseRxFragment() { recycler.adapter = adapter // Set the layout manager for the recycler and fixed size. - recycler.layoutManager = LinearLayoutManager(activity) + recycler.layoutManager = NpaLinearLayoutManager(activity) recycler.setHasFixedSize(true) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt index 6d99d6971..48502887c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt @@ -16,7 +16,7 @@ import java.util.* * * @param fragment the fragment containing this adapter. */ -class LibraryCategoryAdapter(private val fragment: LibraryCategoryFragment) : +class LibraryCategoryAdapter(val fragment: LibraryCategoryFragment) : FlexibleAdapter() { /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.kt index 77a5f8b30..f259681e4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.kt @@ -19,7 +19,7 @@ import kotlinx.android.synthetic.main.item_catalogue_grid.view.* * @param listener a listener to react to single tap and long tap events. * @constructor creates a new library holder. */ -class LibraryHolder(private val view: View, adapter: LibraryCategoryAdapter, listener: FlexibleViewHolder.OnListItemClickListener) : +class LibraryHolder(private val view: View, private val adapter: LibraryCategoryAdapter, listener: FlexibleViewHolder.OnListItemClickListener) : FlexibleViewHolder(view, adapter, listener) { private var manga: Manga? = null @@ -55,9 +55,9 @@ class LibraryHolder(private val view: View, adapter: LibraryCategoryAdapter, lis * @param coverCache the cache that stores the cover in the filesystem. */ private fun loadCover(manga: Manga, source: Source, coverCache: CoverCache) { - if (manga.thumbnail_url != null) { + if (!manga.thumbnail_url.isNullOrEmpty()) { coverCache.saveOrLoadFromCache(manga.thumbnail_url, source.glideHeaders) { - if (this.manga == manga) { + if (adapter.fragment.isResumed && this.manga == manga) { Glide.with(view.context) .load(it) .diskCacheStrategy(DiskCacheStrategy.RESULT) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersFragment.kt index f94cbe022..c70d7f3fe 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersFragment.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersFragment.kt @@ -5,7 +5,6 @@ import android.animation.AnimatorListenerAdapter import android.content.Intent import android.os.Bundle import android.support.v7.view.ActionMode -import android.support.v7.widget.LinearLayoutManager import android.view.* import com.afollestad.materialdialogs.MaterialDialog import eu.davidea.flexibleadapter.FlexibleAdapter @@ -22,6 +21,7 @@ import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.util.getCoordinates import eu.kanade.tachiyomi.util.getResourceDrawable import eu.kanade.tachiyomi.util.toast +import eu.kanade.tachiyomi.widget.NpaLinearLayoutManager import kotlinx.android.synthetic.main.fragment_manga_chapters.* import nucleus.factory.RequiresPresenter import rx.Observable @@ -66,7 +66,7 @@ class ChaptersFragment : BaseRxFragment(), ActionMode.Callbac adapter = ChaptersAdapter(this) recycler.adapter = adapter - recycler.layoutManager = LinearLayoutManager(activity) + recycler.layoutManager = NpaLinearLayoutManager(activity) recycler.addItemDecoration(DividerItemDecoration( context.theme.getResourceDrawable(R.attr.divider_drawable))) recycler.setHasFixedSize(true) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt index 2b078a40c..70d522c96 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt @@ -51,8 +51,8 @@ class ReaderPresenter : BasePresenter() { private var previousChapter: Chapter? = null private var mangaSyncList: List? = null - private lateinit var retryPageSubject: PublishSubject - private lateinit var pageInitializerSubject: PublishSubject + private val retryPageSubject by lazy { PublishSubject.create() } + private val pageInitializerSubject by lazy { PublishSubject.create() } val isSeamlessMode by lazy { prefs.seamlessMode() } @@ -120,7 +120,6 @@ class ReaderPresenter : BasePresenter() { private fun initializeSubjects() { // Listen for pages initialization events - pageInitializerSubject = PublishSubject.create() add(pageInitializerSubject.observeOn(Schedulers.io()) .concatMap { ch -> val observable: Observable @@ -141,7 +140,6 @@ class ReaderPresenter : BasePresenter() { }.subscribe()) // Listen por retry events - retryPageSubject = PublishSubject.create() add(retryPageSubject.observeOn(Schedulers.io()) .flatMap { page -> if (page.imageUrl == null) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersFragment.kt index 1fecbaf42..fbaa5c7cb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersFragment.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/RecentChaptersFragment.kt @@ -1,7 +1,6 @@ package eu.kanade.tachiyomi.ui.recent import android.os.Bundle -import android.support.v7.widget.LinearLayoutManager import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -17,6 +16,7 @@ import eu.kanade.tachiyomi.ui.base.fragment.BaseRxFragment import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.util.getResourceDrawable +import eu.kanade.tachiyomi.widget.NpaLinearLayoutManager import kotlinx.android.synthetic.main.fragment_recent_chapters.* import nucleus.factory.RequiresPresenter import rx.Observable @@ -67,7 +67,7 @@ class RecentChaptersFragment : BaseRxFragment(), Flexib */ override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { // Init RecyclerView and adapter - recycler.layoutManager = LinearLayoutManager(activity) + recycler.layoutManager = NpaLinearLayoutManager(activity) recycler.addItemDecoration(DividerItemDecoration(context.theme.getResourceDrawable(R.attr.divider_drawable))) recycler.setHasFixedSize(true) adapter = RecentChaptersAdapter(this) diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/NpaGridLayoutManager.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/NpaGridLayoutManager.kt new file mode 100644 index 000000000..f34e4274c --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/NpaGridLayoutManager.kt @@ -0,0 +1,27 @@ +package eu.kanade.tachiyomi.widget + +import android.content.Context +import android.support.v7.widget.GridLayoutManager +import android.util.AttributeSet + +/** + * No Predictive Animations GridLayoutManager + */ +open class NpaGridLayoutManager : GridLayoutManager { + + constructor(context: Context, spanCount: Int) : super(context, spanCount) {} + + constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) + : super(context, attrs, defStyleAttr, defStyleRes) {} + + constructor(context: Context, spanCount: Int, orientation: Int, reverseLayout: Boolean) + : super(context, spanCount, orientation, reverseLayout) {} + + /** + * Disable predictive animations. There is a bug in RecyclerView which causes views that + * are being reloaded to pull invalid ViewHolders from the internal recycler stack if the + * adapter size has decreased since the ViewHolder was recycled. + */ + override fun supportsPredictiveItemAnimations() = false + +} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/NpaLinearLayoutManager.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/NpaLinearLayoutManager.kt new file mode 100644 index 000000000..ec754efcb --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/NpaLinearLayoutManager.kt @@ -0,0 +1,27 @@ +package eu.kanade.tachiyomi.widget + +import android.content.Context +import android.support.v7.widget.LinearLayoutManager +import android.util.AttributeSet + +/** + * No Predictive Animations LinearLayoutManager + */ +open class NpaLinearLayoutManager : LinearLayoutManager { + + constructor(context: Context): super(context) {} + + constructor(context: Context, orientation: Int, reverseLayout: Boolean) + : super(context, orientation, reverseLayout) {} + + constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) + : super(context, attrs, defStyleAttr, defStyleRes) {} + + /** + * Disable predictive animations. There is a bug in RecyclerView which causes views that + * are being reloaded to pull invalid ViewHolders from the internal recycler stack if the + * adapter size has decreased since the ViewHolder was recycled. + */ + override fun supportsPredictiveItemAnimations() = false + +} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/PreCachingLayoutManager.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/PreCachingLayoutManager.kt index 629a1b641..525b92c29 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/PreCachingLayoutManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/PreCachingLayoutManager.kt @@ -1,10 +1,9 @@ package eu.kanade.tachiyomi.widget import android.content.Context -import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.RecyclerView -class PreCachingLayoutManager(context: Context) : LinearLayoutManager(context) { +class PreCachingLayoutManager(context: Context) : NpaLinearLayoutManager(context) { companion object { const val DEFAULT_EXTRA_LAYOUT_SPACE = 600 @@ -19,7 +18,4 @@ class PreCachingLayoutManager(context: Context) : LinearLayoutManager(context) { return DEFAULT_EXTRA_LAYOUT_SPACE } - // http://stackoverflow.com/questions/30220771/recyclerview-inconsistency-detected-invalid-item-position - override fun supportsPredictiveItemAnimations() = false - }