微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

带有2个recyclerview的Viewpager2内存泄漏 ProfileFragment ViewPagerAdapter Recylerview适配器viewpager的内容

如何解决带有2个recyclerview的Viewpager2内存泄漏 ProfileFragment ViewPagerAdapter Recylerview适配器viewpager的内容

我有一个带有2个recyclerview的viewpager (试图在Instagram用户个人资料中实施帖子部分) 问题是我不断出现内存泄漏。当我阅读LeakCanary日志时,它说内存泄漏的原因是viewpager。这是leakCanary片段

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

这是我的代码

ProfileFragment

这是使用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://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
    }


}

ViewPagerAdapter

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,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)
    }


}

Recylerview适配器(viewpager的内容

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
                ),false
        )
        return PhotoGridViewHolder(itembinding,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,type : AdapterType)
        }
    }
    
    enum class AdapterType {
        Tagged,Post
    }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。