Android 带有2个recyclerview内存泄漏的Viewpager2

Android 带有2个recyclerview内存泄漏的Viewpager2,android,android-recyclerview,memory-leaks,android-viewpager2,leakcanary,Android,Android Recyclerview,Memory Leaks,Android Viewpager2,Leakcanary,我有一个带有2个recyclerview的viewpager (尝试在Instagram用户配置文件中实现post节) 问题是我的内存一直在泄漏。当我阅读leakCanary日志时,它说内存泄漏的原因是viewpager。这是泄漏的金丝雀片段 2020-05-13 17:57:32.914 D/LeakCanary: ┬─── 2020-05-13 17:57:32.914 D/LeakCanary: │ GC Root: Local variable in native code 2020-0

我有一个带有2个recyclerview的viewpager (尝试在Instagram用户配置文件中实现post节) 问题是我的内存一直在泄漏。当我阅读leakCanary日志时,它说内存泄漏的原因是viewpager。这是泄漏的金丝雀片段

2020-05-13 17:57:32.914 D/LeakCanary: ┬───
2020-05-13 17:57:32.914 D/LeakCanary: │ GC Root: Local variable in native code
2020-05-13 17:57:32.914 D/LeakCanary: │
2020-05-13 17:57:32.914 D/LeakCanary: ├─ android.net.ConnectivityThread instance
2020-05-13 17:57:32.914 D/LeakCanary: │    Leaking: NO (PathClassLoader↓ is not leaking)
2020-05-13 17:57:32.914 D/LeakCanary: │    Thread name: 'ConnectivityThread'
2020-05-13 17:57:32.914 D/LeakCanary: │    ↓ ConnectivityThread.contextClassLoader
2020-05-13 17:57:32.914 D/LeakCanary: ├─ dalvik.system.PathClassLoader instance
2020-05-13 17:57:32.914 D/LeakCanary: │    Leaking: NO (ViewDataBinding↓ is not leaking and A ClassLoader is never leaking)
2020-05-13 17:57:32.914 D/LeakCanary: │    ↓ PathClassLoader.runtimeInternalObjects
2020-05-13 17:57:32.914 D/LeakCanary: ├─ java.lang.Object[] array
2020-05-13 17:57:32.914 D/LeakCanary: │    Leaking: NO (ViewDataBinding↓ is not leaking)
2020-05-13 17:57:32.914 D/LeakCanary: │    ↓ Object[].[349]
2020-05-13 17:57:32.914 D/LeakCanary: ├─ androidx.databinding.ViewDataBinding class
2020-05-13 17:57:32.914 D/LeakCanary: │    Leaking: NO (RouteInfoFragment↓ is not leaking and a class is never leaking)
2020-05-13 17:57:32.914 D/LeakCanary: │    ↓ static ViewDataBinding.sReferenceQueue
2020-05-13 17:57:32.914 D/LeakCanary: ├─ java.lang.ref.ReferenceQueue instance
2020-05-13 17:57:32.914 D/LeakCanary: │    Leaking: NO (RouteInfoFragment↓ is not leaking)
2020-05-13 17:57:32.914 D/LeakCanary: │    ↓ ReferenceQueue.head
2020-05-13 17:57:32.914 D/LeakCanary: ├─ androidx.databinding.ViewDataBinding$WeakListener instance
2020-05-13 17:57:32.914 D/LeakCanary: │    Leaking: NO (RouteInfoFragment↓ is not leaking)
2020-05-13 17:57:32.914 D/LeakCanary: │    ↓ ViewDataBinding$WeakListener.mObservable
2020-05-13 17:57:32.914 D/LeakCanary: ├─ androidx.databinding.ViewDataBinding$LiveDataListener instance
2020-05-13 17:57:32.914 D/LeakCanary: │    Leaking: NO (RouteInfoFragment↓ is not leaking)
2020-05-13 17:57:32.914 D/LeakCanary: │    ↓ ViewDataBinding$LiveDataListener.mLifecycleOwner
2020-05-13 17:57:32.914 D/LeakCanary: ├─ iclaude.berlinwanderer.features.route.ui.route_dashboard.route_info.RouteInfoFragment instance
2020-05-13 17:57:32.915 D/LeakCanary: │    Leaking: NO (RouteDashboardFragment↓ is not leaking and Fragment#mFragmentManager is not null)
2020-05-13 17:57:32.915 D/LeakCanary: │    Fragment.mTag=f0
2020-05-13 17:57:32.915 D/LeakCanary: │    ↓ RouteInfoFragment.mParentFragment
2020-05-13 17:57:32.915 D/LeakCanary: ├─ iclaude.berlinwanderer.features.route.ui.route_dashboard.RouteDashboardFragment instance
2020-05-13 17:57:32.915 D/LeakCanary: │    Leaking: NO (Fragment#mFragmentManager is not null)
2020-05-13 17:57:32.915 D/LeakCanary: │    ↓ RouteDashboardFragment.mLifecycleRegistry
2020-05-13 17:57:32.915 D/LeakCanary: │                             ~~~~~~~~~~~~~~~~~~
2020-05-13 17:57:32.915 D/LeakCanary: ├─ androidx.lifecycle.LifecycleRegistry instance
2020-05-13 17:57:32.915 D/LeakCanary: │    Leaking: UNKNOWN
2020-05-13 17:57:32.915 D/LeakCanary: │    ↓ LifecycleRegistry.mObserverMap
2020-05-13 17:57:32.915 D/LeakCanary: │                        ~~~~~~~~~~~~
2020-05-13 17:57:32.915 D/LeakCanary: ├─ androidx.arch.core.internal.FastSafeIterableMap instance
2020-05-13 17:57:32.915 D/LeakCanary: │    Leaking: UNKNOWN
2020-05-13 17:57:32.915 D/LeakCanary: │    ↓ FastSafeIterableMap.mHashMap
2020-05-13 17:57:32.915 D/LeakCanary: │                          ~~~~~~~~
2020-05-13 17:57:32.915 D/LeakCanary: ├─ java.util.HashMap instance
2020-05-13 17:57:32.915 D/LeakCanary: │    Leaking: UNKNOWN
2020-05-13 17:57:32.915 D/LeakCanary: │    ↓ HashMap.table
2020-05-13 17:57:32.915 D/LeakCanary: │              ~~~~~
2020-05-13 17:57:32.915 D/LeakCanary: ├─ java.util.HashMap$Node[] array
2020-05-13 17:57:32.915 D/LeakCanary: │    Leaking: UNKNOWN
2020-05-13 17:57:32.915 D/LeakCanary: │    ↓ HashMap$Node[].[1]
2020-05-13 17:57:32.915 D/LeakCanary: │                     ~~~
2020-05-13 17:57:32.915 D/LeakCanary: ├─ java.util.HashMap$Node instance
2020-05-13 17:57:32.915 D/LeakCanary: │    Leaking: UNKNOWN
2020-05-13 17:57:32.915 D/LeakCanary: │    ↓ HashMap$Node.key
2020-05-13 17:57:32.915 D/LeakCanary: │                   ~~~
2020-05-13 17:57:32.915 D/LeakCanary: ├─ androidx.viewpager2.adapter.FragmentStateAdapter$5 instance
2020-05-13 17:57:32.915 D/LeakCanary: │    Leaking: UNKNOWN
2020-05-13 17:57:32.915 D/LeakCanary: │    Anonymous class implementing androidx.lifecycle.LifecycleEventObserver
2020-05-13 17:57:32.915 D/LeakCanary: │    ↓ FragmentStateAdapter$5.this$0
2020-05-13 17:57:32.916 D/LeakCanary: │                             ~~~~~~
2020-05-13 17:57:32.916 D/LeakCanary: ├─ iclaude.berlinwanderer.features.route.ui.route_dashboard.RouteDashboardViewPagerAdapter instance
2020-05-13 17:57:32.916 D/LeakCanary: │    Leaking: UNKNOWN
2020-05-13 17:57:32.916 D/LeakCanary: │    ↓ RouteDashboardViewPagerAdapter.mObservable
2020-05-13 17:57:32.916 D/LeakCanary: │                                     ~~~~~~~~~~~
2020-05-13 17:57:32.916 D/LeakCanary: ├─ androidx.recyclerview.widget.RecyclerView$AdapterDataObservable instance
2020-05-13 17:57:32.916 D/LeakCanary: │    Leaking: UNKNOWN
2020-05-13 17:57:32.916 D/LeakCanary: │    ↓ RecyclerView$AdapterDataObservable.mObservers
2020-05-13 17:57:32.916 D/LeakCanary: │                                         ~~~~~~~~~~
2020-05-13 17:57:32.916 D/LeakCanary: ├─ java.util.ArrayList instance
2020-05-13 17:57:32.916 D/LeakCanary: │    Leaking: UNKNOWN
2020-05-13 17:57:32.916 D/LeakCanary: │    ↓ ArrayList.elementData
2020-05-13 17:57:32.916 D/LeakCanary: │                ~~~~~~~~~~~
2020-05-13 17:57:32.916 D/LeakCanary: ├─ java.lang.Object[] array
2020-05-13 17:57:32.916 D/LeakCanary: │    Leaking: UNKNOWN
2020-05-13 17:57:32.916 D/LeakCanary: │    ↓ Object[].[0]
2020-05-13 17:57:32.916 D/LeakCanary: │               ~~~
2020-05-13 17:57:32.916 D/LeakCanary: ├─ com.google.android.material.tabs.TabLayoutMediator$PagerAdapterObserver instance
2020-05-13 17:57:32.916 D/LeakCanary: │    Leaking: UNKNOWN
2020-05-13 17:57:32.916 D/LeakCanary: │    ↓ TabLayoutMediator$PagerAdapterObserver.this$0
2020-05-13 17:57:32.916 D/LeakCanary: │                                             ~~~~~~
2020-05-13 17:57:32.916 D/LeakCanary: ├─ com.google.android.material.tabs.TabLayoutMediator instance
2020-05-13 17:57:32.916 D/LeakCanary: │    Leaking: UNKNOWN
2020-05-13 17:57:32.916 D/LeakCanary: │    ↓ TabLayoutMediator.tabLayout
2020-05-13 17:57:32.916 D/LeakCanary: │                        ~~~~~~~~~
2020-05-13 17:57:32.916 D/LeakCanary: ├─ com.google.android.material.tabs.TabLayout instance
2020-05-13 17:57:32.916 D/LeakCanary: │    Leaking: YES (View detached and has parent)
2020-05-13 17:57:32.916 D/LeakCanary: │    mContext instance of iclaude.berlinwanderer.features.route.ui.RouteActivity with mDestroyed = false
2020-05-13 17:57:32.916 D/LeakCanary: │    View#mParent is set
2020-05-13 17:57:32.916 D/LeakCanary: │    View#mAttachInfo is null (view detached)
2020-05-13 17:57:32.916 D/LeakCanary: │    View.mID = R.id.tab_layout
2020-05-13 17:57:32.916 D/LeakCanary: │    View.mWindowAttachCount = 1
2020-05-13 17:57:32.916 D/LeakCanary: │    ↓ TabLayout.mParent
2020-05-13 17:57:32.916 D/LeakCanary: ╰→ androidx.constraintlayout.motion.widget.MotionLayout instance
2020-05-13 17:57:32.916 D/LeakCanary: ​     Leaking: YES (ObjectWatcher was watching this because iclaude.berlinwanderer.features.route.ui.route_dashboard.RouteDashboardFragment received Fragment#onDestroyView() callback (references to its views should be cleared to prevent leaks))
2020-05-13 17:57:32.916 D/LeakCanary: ​     key = 9c28ffc6-b1ce-4316-b015-c4df278892a1
2020-05-13 17:57:32.916 D/LeakCanary: ​     watchDurationMillis = 36154
2020-05-13 17:57:32.916 D/LeakCanary: ​     retainedDurationMillis = 31130
2020-05-13 17:57:32.916 D/LeakCanary: ​     mContext instance of iclaude.berlinwanderer.features.route.ui.RouteActivity with mDestroyed = false
2020-05-13 17:57:32.917 D/LeakCanary: ​     View#mParent is null
2020-05-13 17:57:32.917 D/LeakCanary: ​     View#mAttachInfo is null (view detached)
2020-05-13 17:57:32.917 D/LeakCanary: ​     View.mID = R.id.ml_main
2020-05-13 17:57:32.917 D/LeakCanary: ​     View.mWindowAttachCount = 1
这是我的密码 轮廓片段 这是使用viewpager的片段
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import com.bumptech.glide.Glide
import com.bumptech.glide.RequestManager
import com.bumptech.glide.request.RequestOptions
import com.fdev.instagramclone.R
import com.fdev.instagramclone.business.domain.model.User
import com.fdev.instagramclone.databinding.FragmentProfileBinding
import com.fdev.instagramclone.framework.datasource.network.implementation.UserFirestoreServiceImpl
import com.fdev.instagramclone.framework.presentation.main.BaseMainFragment
import com.fdev.instagramclone.util.printLogD
import com.google.android.material.tabs.TabLayoutMediator
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview

@FlowPreview
@ExperimentalCoroutinesApi
@AndroidEntryPoint
class ProfileFragment : BaseMainFragment(R.layout.fragment_profile), PhotoGridAdapter.Interaction, PostViewPagerAdapter.Interaction {

    companion object {
        const val PAGE_NUMBER = 2
    }

    private var _binding: FragmentProfileBinding? = null


    private val binding
        get() = _binding!!

    private val viewModel: ProfileViewModel by viewModels()

    private var _postViewPagerAdapter: PostViewPagerAdapter? = null

    private val postViewPagerAdapter
        get() = _postViewPagerAdapter!!


    private val tabDrawable = listOf(R.drawable.ic_baseline_grid_on_24, R.drawable.ic_baseline_account_box_24)

    private var requestManager: RequestManager? = null

    lateinit var tabLayoutMediator: TabLayoutMediator


    private var images1 = listOf(
            "https://www.worldwomanfoundation.com/wp-content/uploads/2018/09/Jeannette_Ceja-_Head_Shot_2018_0-770x330.jpg",
            "https://womensagenda.com.au/wp-content/uploads/2020/05/Sarah-Hill-002-1024x683.jpeg",
            "https://news.harvard.edu/wp-content/uploads/2020/06/Durba_Mitra-copy_2500-1200x800.jpg",
            "https://images.idgesg.net/images/article/2020/01/women-in-it_daphne-jones-100828118-large.jpg",
            "https://vtnews.vt.edu/content/vtnews_vt_edu/en/articles/2020/04/science-women-in-data-science-online/_jcr_content/article-image.transform/m-medium/image.jpg",

            )

    private var images2 = listOf(
            "https://koreanindo.net/wp-content/uploads/2019/02/everglow-wang-yiren.jpg",
            "https://kepoper.com/wp-content/uploads/2019/10/Mina-Twice-Wiki-1-758x620.jpg",
            "https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcQT1uidd0fswlshWotS43XDLyscw6ZtFw-E3Q&usqp=CAU",
            "https://cdn.idntimes.com/content-images/community/2020/04/20200417-142524-373be8fe5157e9ca9a24a8951ab21dda.jpg",
            "https://i.redd.it/21csbponb0551.jpg",
            "https://i.pinimg.com/originals/24/5d/87/245d87d800391ff353c04aed8eb52a50.jpg",
            "https://womensagenda.com.au/wp-content/uploads/2020/05/Sarah-Hill-002-1024x683.jpeg",
            "https://news.harvard.edu/wp-content/uploads/2020/06/Durba_Mitra-copy_2500-1200x800.jpg",
            "https://images.idgesg.net/images/article/2020/01/women-in-it_daphne-jones-100828118-large.jpg"
    )

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        _binding = FragmentProfileBinding.inflate(inflater, container, false)
        val view = binding.root
        return view
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initObserver()
        initUI(view)
        postViewPagerAdapter.addItemToPost(images2)
        postViewPagerAdapter.addItemToTagged(images1)
    }


    private fun initUI(view: View) {
        initViewPager(view)
    }

    private fun initViewPager(view: View) {
        setupGlide()

        _postViewPagerAdapter = PostViewPagerAdapter(requestManager as RequestManager, this, this)

        binding.contentViewpager.adapter = postViewPagerAdapter

        tabLayoutMediator = TabLayoutMediator(binding.contentTabLayout, binding.contentViewpager) { tab, position ->
            tab.setIcon(tabDrawable[position])
        }

        tabLayoutMediator.attach()


    }

    private fun initObserver() {
        viewModel.sessionManager.currentUser.observe(viewLifecycleOwner, { user ->
            user?.let {
                setUI(it)
            }
        })
    }


    private fun setUI(user: User) {
        binding.apply {

            usernameTv.text = user.username

            followersTv.text = user.followers.size.toString()

            followingTv.text = user.following.size.toString()

            bioTv.text = user.bio
            fullnameTv.text = user.name

            if (!user.profileImage.equals(UserFirestoreServiceImpl.USER_DEFAULT_PICTURE_URL)) {
                (requestManager as RequestManager)
                        .load(user.profileImage)
                        .into(profileCircleimageview)
            }


        }
    }


    private fun setupGlide() {
        val requestOptions = RequestOptions
                .placeholderOf(R.drawable.default_image)
                .error(R.drawable.ic_baseline_error_outline_24)

        activity?.let {
            requestManager = Glide.with(it)
                    .applyDefaultRequestOptions(requestOptions)
        }
    }

    override fun onItemSelected(position: Int, item: String, type: AdapterType) {
        when (type) {

            AdapterType.Post -> {
                Toast.makeText(context, "Post $position", Toast.LENGTH_SHORT).show()
            }


            AdapterType.Tagged -> {
                Toast.makeText(context, "Tagged $position", Toast.LENGTH_SHORT).show()
            }

        }
    }


    override fun onNextPage(type: Int) {

    }

    override fun onPause() {
        super.onPause()
        binding.swipeRefreshLayout.isEnabled = false
    }


    override fun afterScrolled(isFirstItem: Boolean) {
        binding.swipeRefreshLayout.isEnabled = isFirstItem
    }

    override fun onDestroyView() {
        super.onDestroyView()
        tabLayoutMediator.detach()
//        binding.contentViewpager.adapter = null
        requestManager = null
        _binding = null
    }


}
视页雷达
导入android.content.Context
导入android.view.LayoutInflater
导入android.view.view
导入android.view.ViewGroup
导入androidx.recyclerview.widget*
导入com.bumptech.glide.RequestManager
import com.fdev.instagramclone.R
导入com.fdev.instagramclone.databinding.ViewpagerPostItemBinding
导入com.fdev.instagramclone.util.printLogD
导入kotlinx.android.synthetic.main.viewpager\u post\u item.view*
类PostViewPagerAdapter(
var requestManager:requestManager,
交互:PhotoGridAdapter。交互,
var onNextPageInteraction:交互
) :
RecyclerView.Adapter(){
伴星{
const val POST=1
常量值=2
}
私有变量adapterList=ArrayList()
专用var后适配器:PhotoGridAdapter
私有变量taggedAdapter:PhotoGridAdapter
初始化{
postAdapter=PhotoGridAdapter(
请求管理器,
相互作用
AdapterType.Post
)
taggedAdapter=PhotoGridAdapter(
请求管理器,
相互作用
AdapterType.taged
)
adapterList.add(后适配器)
adapterList.add(taggedAdapter)
}
override fun onCreateViewHolder(父级:ViewGroup,viewType:Int):RecyclerView.ViewHolder{
//val binding=VIEWPAGERPOTITEMBINDING.FLATE(
//LayoutFlater.from(父上下文),
//家长,假
//        )
val view=LayoutInflater.from(parent.context).充气(
R.layout.viewpager\u post\u项,
父母亲
假的
)
返回ViewPagerAdapterViewHolder(视图,onNextPageInteraction)
}
覆盖onBindViewHolder(holder:RecyclerView.ViewHolder,位置:Int){
何时(持有人){
是ViewPagerAdapterViewHolder->{
固定器绑定(适配器列表[位置])
}
}
}
重写getItemCount():Int{
返回适配器列表.size
}
趣味addItemToTagged(列表:列表){
taggedAdapter.com(
请求管理器,
列表
)
taggedAdapter.submitList(列表)
}
趣味addItemToPost(列表:列表){
后适应。预适应图像(
请求管理器,
列表
)
postAdapter.submitList(列表)
}
类ViewPagerAdapterViewHolder
建造师(
var itemView:View,
互动:互动,
):RecyclerView.ViewHolder(项目视图){
趣味绑定(项目:PhotoGridAdapter)=与(项目视图){
initRecylerView(itemView.post_recylerview,item)
}
private fun initRecylerView(recyclerView:recyclerView,recyclerViewAdapter:PhotoGridAdapter){
回收视图{
val gridLayout=GridLayoutManager(上下文,3)
layoutManager=gridLayout
setHasFixedSize(真)
addOnScrollListener(对象:RecyclerView.OnScrollListener(){
覆盖CrollStateChanged(recyclerView:recyclerView,newState:Int){
super.onScrollStateChanged(recyclerView、newState)
val layoutManager=recyclerView.layoutManager作为LinearLayoutManager
val lastPosition=layoutManager.findLastVisibleItemPosition()
如果(lastPosition==RecycleServiceAdapter.itemCount.减去(1)){
interaction.onNextPage(适配器位置)
}
}
})
addOnScrollListener(对象:RecyclerView.OnScrollListener(){
覆盖已克隆的乐趣(recyclerView:recyclerView,dx:Int,dy:Int){
super.onScrolled(回收视图、dx、dy)
interaction.afterScrolled(gridLayout.findFirstCompletelyVisibleItemPosition()==0)
}
})
适配器=回收服务适配器
}
}
}
界面相互作用{
下一页(类型:Int)
有趣的余弦(isFirstItem:Boolean)
}
}
Recylerview适配器(viewpager的内容)
导入android.content.Context
导入androidx.recyclerview.widget.recyclerview
导入android.view.LayoutInflater
导入android.view.ViewGroup
导入androidx.recyclerview.widget.AsyncListDifferent
导入androidx.recyclerview.widget.DiffUtil
导入com.bumptech.glide.RequestManager
导入com.fdev.instagramclone.databinding.PhotoGridItemContainerBinding
导入com.bumptech.glide.load.resource.drawable.drawable TransitionOptions.withCrossFade
导入com.fdev.instagramclone.util.printLogD
类PhotoGridAdapter(
私有val请求管理器:请求管理器,
私有val交互:交互?=null,
私有值类型:AdapterType
) :
RecyclerView.Adapter(){
val DIFF_CALLBACK=对象:DiffUtil.ItemCallback(){
覆盖乐趣项相同(旧项:字符串,新项:字符串):布尔值{
返回oldItem==newItem
}
覆盖内容相同(旧项:字符串,新项:字符串):布尔值{
返回oldItem==newItem
}
}
private val difference=AsyncListDifference(这是DIFF_回调)
override fun onCreateViewHolder(父级:ViewGroup,viewType:Int):RecyclerView.ViewHolder{
val itemBinding=PhotoGridItemContainerBinding.inflate(
从
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.*
import com.bumptech.glide.RequestManager
import com.fdev.instagramclone.R
import com.fdev.instagramclone.databinding.ViewpagerPostItemBinding
import com.fdev.instagramclone.util.printLogD
import kotlinx.android.synthetic.main.viewpager_post_item.view.*

class PostViewPagerAdapter(
        var requestManager: RequestManager,
        interaction: PhotoGridAdapter.Interaction,
        var onNextPageInteraction: Interaction
) :
        RecyclerView.Adapter<RecyclerView.ViewHolder>() {



    companion object{
        const val POST = 1
        const val TAGGED = 2
    }

    private var adapterList = ArrayList<PhotoGridAdapter>()


    private var postAdapter: PhotoGridAdapter



    private var taggedAdapter: PhotoGridAdapter


    init {

        postAdapter = PhotoGridAdapter(
                requestManager,
                interaction,
                AdapterType.Post
        )






        taggedAdapter = PhotoGridAdapter(
                requestManager,
                interaction,
                AdapterType.Tagged
        )



        adapterList.add(postAdapter)
        adapterList.add(taggedAdapter)



    }





    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
//        val binding = ViewpagerPostItemBinding.inflate(
//                LayoutInflater.from(parent.context),
//                parent,false
//        )
        val view = LayoutInflater.from(parent.context).inflate(
                R.layout.viewpager_post_item,
                parent,
                false
        )
        return ViewPagerAdapterViewHolder(view , onNextPageInteraction)
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (holder) {
            is ViewPagerAdapterViewHolder -> {
                holder.bind(adapterList[position])
            }
        }
    }

    override fun getItemCount(): Int {
        return adapterList.size
    }

    fun addItemToTagged(list : List<String>) {
        taggedAdapter.preloadGlideImages(
                requestManager,
                list
        )
        taggedAdapter.submitList(list)
    }

    fun addItemToPost(list : List<String>) {
        postAdapter.preloadGlideImages(
                requestManager,
                list
        )
        postAdapter.submitList(list)
    }



    class ViewPagerAdapterViewHolder
    constructor(
            var itemView : View,
            var interaction: Interaction,
    ) : RecyclerView.ViewHolder(itemView) {

        fun bind(item : PhotoGridAdapter) = with(itemView) {
            initRecylerView(itemView.post_recylerview , item)
        }

        private fun initRecylerView(recyclerView: RecyclerView, recyclerViewAdapter : PhotoGridAdapter){
            recyclerView.apply{
                val gridLayout = GridLayoutManager( context, 3)
                layoutManager = gridLayout
                setHasFixedSize(true)
                addOnScrollListener(object : RecyclerView.OnScrollListener(){
                    override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                        super.onScrollStateChanged(recyclerView, newState)
                        val layoutManager = recyclerView.layoutManager as LinearLayoutManager
                        val lastPosition = layoutManager.findLastVisibleItemPosition()
                        if(lastPosition == recyclerViewAdapter.itemCount.minus(1)){
                            interaction.onNextPage(adapterPosition)
                        }
                    }
                })

                addOnScrollListener(object : RecyclerView.OnScrollListener(){
                    override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                        super.onScrolled(recyclerView, dx, dy)
                        interaction.afterScrolled(gridLayout.findFirstCompletelyVisibleItemPosition() == 0)
                    }
                })


                adapter = recyclerViewAdapter
            }
        }

    }

    interface Interaction {
        fun onNextPage(type : Int)
        fun afterScrolled(isFirstItem : Boolean)
    }


}
import android.content.Context
import androidx.recyclerview.widget.RecyclerView
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.AsyncListDiffer
import androidx.recyclerview.widget.DiffUtil
import com.bumptech.glide.RequestManager
import com.fdev.instagramclone.databinding.PhotoGridItemContainerBinding
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade
import com.fdev.instagramclone.util.printLogD


class PhotoGridAdapter(
        private val requestManager: RequestManager,
        private val interaction: Interaction? = null,
        private val type : AdapterType
) :
        RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    val DIFF_CALLBACK = object : DiffUtil.ItemCallback<String>() {

        override fun areItemsTheSame(oldItem: String, newItem: String): Boolean {
            return oldItem == newItem
        }

        override fun areContentsTheSame(oldItem: String, newItem: String): Boolean {
            return oldItem == newItem
        }

    }
    private val differ = AsyncListDiffer(this, DIFF_CALLBACK)


    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val itemBinding = PhotoGridItemContainerBinding.inflate(
                LayoutInflater.from(
                        parent.context
                ),parent , false
        )
        return PhotoGridViewHolder(itemBinding , interaction , requestManager , type)
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (holder) {
            is PhotoGridViewHolder-> {
                holder.bind(differ.currentList.get(position))
            }
        }
    }

    override fun getItemCount(): Int {
        return differ.currentList.size
    }

    fun submitList(list: List<String>) {
        differ.submitList(list)
    }

    //To preload the image and cache it
    fun preloadGlideImages(
            requestManager: RequestManager ,
                imagesURL : List<String>
        ){
            for(url in imagesURL){
                requestManager
                        .load(url)
                        .preload()
            }
        }
    
        class PhotoGridViewHolder
        constructor(
                private val photoGridBinding: PhotoGridItemContainerBinding,
                private val interaction: Interaction?,
                private val requestManager: RequestManager,
                private val type : AdapterType
        ) : RecyclerView.ViewHolder(photoGridBinding.root) {
    
            fun bind(item: String) = with(photoGridBinding) {
                postImage.setOnClickListener {
                    interaction?.onItemSelected(adapterPosition, item , type)
                }
    
                requestManager
                        .load(item)
                        .transition(withCrossFade())
                        .into(postImage)
    
            }
        }
    
        interface Interaction {
            fun onItemSelected(position: Int, item: String, type : AdapterType)
        }
    }
    
    enum class AdapterType {
        Tagged, Post
    }