亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android性能優化之ViewPagers+Fragment緩存優化怎么實現

發布時間:2022-08-29 16:59:15 來源:億速云 閱讀:162 作者:iii 欄目:開發技術

這篇文章主要介紹“Android性能優化之ViewPagers+Fragment緩存優化怎么實現”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“Android性能優化之ViewPagers+Fragment緩存優化怎么實現”文章能幫助大家解決問題。

    前言

    大家看標題,可能會有點兒懵,什么是ViewPagers,因為在很久之前,我們使用的都是ViewPager,但是現在更多的是在用ViewPager2,因此用ViewPagers(ViewPager、ViewPager2)來代替兩者,主要介紹兩者的區別。

    ViewPagers嵌套Fragment架構,在我們常用的App中隨處可見,抖音的首頁、各大電商app首頁(淘寶、京東、拼多多)等,通過左右滑動切換Tab;但因為ViewPager的預加載機制存在,

    我們先看下ViewPager的源碼:

    public void setOffscreenPageLimit(int limit) {
        if (limit < DEFAULT_OFFSCREEN_PAGES) {
            Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to "
                    + DEFAULT_OFFSCREEN_PAGES);
            limit = DEFAULT_OFFSCREEN_PAGES;
        }
        if (limit != mOffscreenPageLimit) {
            mOffscreenPageLimit = limit;
            populate();
        }
    }

    當我們設置offscreenPageLimit(離屏加載)的數值時,我們可以看到limit的值是有限制,不能小于DEFAULT_OFFSCREEN_PAGES

    private static final int DEFAULT_OFFSCREEN_PAGES = 1;

    那么就意味著ViewPager默認支持預加載,我們看下面這張圖

    Android性能優化之ViewPagers+Fragment緩存優化怎么實現

    如果紅色區域默認為首頁,根據ViewPager默認預加載的閾值,那么左右兩邊的頁面同樣也會被加載,如果有網絡請求,也就是說,我們沒有打開左邊的頁面,它已經默認進行了網絡請求,這種體驗是非常差的,因為會在暗地里消耗流量。

    理想情況下,我們需要的是打開某個頁面的時候才去加載,這里就需要通過懶加載的方式優化。

    1 ViewPager懶加載優化

    1.1 ViewPager的緩存機制

    很多時候,我們在使用Fragment的時候,發現打開過的頁面再回來,頁面沒有重建刷新,很多人覺得是Fragment是有緩存的,其實并不是Fragment有緩存,而是ViewPager具備緩存能力;

    如果有小伙伴使用過單Activity + 多Fragment架構的時候就會發現,打開過的頁面再次返回的時候,Fragment會被重建,所以兩種架構都有利弊,關鍵看我們怎么選擇,下面我們看下ViewPager的緩存機制。

    public void setAdapter(@Nullable PagerAdapter adapter) {
        if (mAdapter != null) {
            ①
            mAdapter.setViewPagerObserver(null);
            mAdapter.startUpdate(this);
            for (int i = 0; i < mItems.size(); i++) {
                final ItemInfo ii = mItems.get(i);
                mAdapter.destroyItem(this, ii.position, ii.object);
            }
            mAdapter.finishUpdate(this);
            mItems.clear();
            removeNonDecorViews();
            mCurItem = 0;
            scrollTo(0, 0);
        }
        ②
        final PagerAdapter oldAdapter = mAdapter;
        mAdapter = adapter;
        mExpectedAdapterCount = 0;
    
        ③
        if (mAdapter != null) {
            if (mObserver == null) {
                mObserver = new PagerObserver();
            }
            mAdapter.setViewPagerObserver(mObserver);
            mPopulatePending = false;
            final boolean wasFirstLayout = mFirstLayout;
            mFirstLayout = true;
            mExpectedAdapterCount = mAdapter.getCount();
            if (mRestoredCurItem >= 0) {
                mAdapter.restoreState(mRestoredAdapterState, mRestoredClassLoader);
                setCurrentItemInternal(mRestoredCurItem, false, true);
                mRestoredCurItem = -1;
                mRestoredAdapterState = null;
                mRestoredClassLoader = null;
            } else if (!wasFirstLayout) {
                ④
                populate();
            } else {
                ⑤
                requestLayout();
            }
        }
    
        // Dispatch the change to any listeners
        if (mAdapterChangeListeners != null && !mAdapterChangeListeners.isEmpty()) {
            for (int i = 0, count = mAdapterChangeListeners.size(); i < count; i++) {
                mAdapterChangeListeners.get(i).onAdapterChanged(this, oldAdapter, adapter);
            }
        }
    }

    核心方法就是setAdapter,像RecyclerView一樣,因為會有緩存,所以當頁面滑動的時候,如果緩存中存在頁面,那么就會從緩存中取,如果沒有,就需要去創建新的頁面,所以我們先來關注一下PagerAdapter

    public abstract class PagerAdapter {
        private final DataSetObservable mObservable = new DataSetObservable();
        private DataSetObserver mViewPagerObserver;
    
        public static final int POSITION_UNCHANGED = -1;
        public static final int POSITION_NONE = -2;
    
        public abstract int getCount();
        //開始更新
        public void startUpdate(@NonNull ViewGroup container) {
            startUpdate((View) container);
        }
        //初始化頁面
        @NonNull
        public Object instantiateItem(@NonNull ViewGroup container, int position) {
            return instantiateItem((View) container, position);
        }
        //銷毀頁面
        public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
            destroyItem((View) container, position, object);
        }
        //結束刷新
        public void finishUpdate(@NonNull ViewGroup container) {
            finishUpdate((View) container);
        }
    }

    PagerAdapter是一個抽象類,那么這些方法肯定是具體實現類實現,如果我們在使用ViewPager嵌套Fragment的時候,使用的是FragmentPageAdapter

    接著回到setAdapter方法中:

    • ①:有一個全局變量 mAdapter,如果是第一個加載進來,那么mAdapter是空的,走到②

    • ②:這里就是將我們傳入的adapter給mAdapter賦值

    • ③:這個時候mAdapter不為空,這里需要關注幾個參數:

    wasFirstLayout = true
    mRestoredCurItem = -1

    所以這里直接走到⑤,調用requestLayout方法,會執行到onMeasure,在這個方法中,會執行populate方法(這個大家自己去爬樓)

    populate干了什么呢?代碼太多了就不貼出來了,直接上圖:

    Android性能優化之ViewPagers+Fragment緩存優化怎么實現

    如果是默認緩存(mOffscreenPageLimit = 1),那么在mItems就會緩存3個Fragment

    private final ArrayList<ItemInfo> mItems = new ArrayList<ItemInfo>();

    當頁面滑動時,page2成為了當前頁,那么ViewPager的populate做了什么操作呢?

    • (1)首先page3會被預加載,這個時候調用了PagerAdapter的instantiateItem方法新建頁面,并放在mItems集合中,并且設置為不可見的狀態(setUserVisibleHint(false)),所有緩存中不可見的頁面同理(2)page1就會從緩存中移除,調用了PagerAdapter的destroyItem方法,curPage會成為mItems中第一個緩存對象;

    • (3)將page2設置為當前展示的Fragment

    因此populate干的主要工作就是,隨著頁面的滑動,將Page從緩存中移除銷毀,或者將新頁面新建加入緩存中。

    1.2 ViewPager懶加載方案

    如上所述,ViewPager默認就是開啟預加載的,而且默認最多能夠緩存3個Fragment頁面,那么為了避免流量的消耗,需要我們針對預加載這種情況進行頁面懶加載,只有當頁面可見的時候,才能加載數據。

    class MainLazyLoadAdapter(
        fragmentManager: FragmentManager,
        val fragments:MutableList<Fragment>
    ) : FragmentPagerAdapter(fragmentManager) {
        override fun getCount(): Int {
            return fragments.size
        }
    
        override fun getItem(position: Int): Fragment {
            return fragments[position]
        }
    }
    class LazyFragment(val index:Int) : Fragment() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            Log.e("TAG","LazyFragment $index onCreate")
        }
    
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            Log.e("TAG","LazyFragment $index onCreateView")
            return inflater.inflate(R.layout.fragment_lazy, container, false)
        }
    
    }
    val fragments = mutableListOf<Fragment>()
    for (index in 0..5) {
        fragments.add(LazyFragment(index))
    }
    vp_lazy_load.adapter = MainLazyLoadAdapter(supportFragmentManager, fragments)

    首先我們先看默認預加載狀態,驗證之前源碼中的原理:

    //第一次進來
    2022-08-28 13:41:15.759 12677-12677/com.lay.image_process E/TAG: LazyFragment 0 onCreate
    2022-08-28 13:41:15.760 12677-12677/com.lay.image_process E/TAG: LazyFragment 0 onCreateView
    2022-08-28 13:41:15.783 12677-12677/com.lay.image_process E/TAG: LazyFragment 1 onCreate
    2022-08-28 13:41:15.784 12677-12677/com.lay.image_process E/TAG: LazyFragment 1 onCreateView

    我們看到第一次進來,第二個Fragment被加載進來,然后右滑,第三個Fragment被加載

    2022-08-28 13:41:15.759 12677-12677/com.lay.image_process E/TAG: LazyFragment 0 onCreate
    2022-08-28 13:41:15.760 12677-12677/com.lay.image_process E/TAG: LazyFragment 0 onCreateView
    2022-08-28 13:41:15.783 12677-12677/com.lay.image_process E/TAG: LazyFragment 1 onCreate
    2022-08-28 13:41:15.784 12677-12677/com.lay.image_process E/TAG: LazyFragment 1 onCreateView
    2022-08-28 13:48:45.248 12677-12677/com.lay.image_process E/TAG: LazyFragment 2 onCreate
    2022-08-28 13:48:45.250 12677-12677/com.lay.image_process E/TAG: LazyFragment 2 onCreateView

    當我們滑到第4個Fragment的時候,左滑回到第3個Fragment,發現并沒有重建是因為緩存的原因,因為滑到第4個Fragment的時候,第2個Fragment已經被銷毀了,再回到第3個Fragment的時候,第2個Fragment被重建,走了onCreateView方法

    2022-08-28 13:41:15.759 12677-12677/com.lay.image_process E/TAG: LazyFragment 0 onCreate
    2022-08-28 13:41:15.760 12677-12677/com.lay.image_process E/TAG: LazyFragment 0 onCreateView
    2022-08-28 13:41:15.783 12677-12677/com.lay.image_process E/TAG: LazyFragment 1 onCreate
    2022-08-28 13:41:15.784 12677-12677/com.lay.image_process E/TAG: LazyFragment 1 onCreateView
    2022-08-28 13:48:45.248 12677-12677/com.lay.image_process E/TAG: LazyFragment 2 onCreate
    2022-08-28 13:48:45.250 12677-12677/com.lay.image_process E/TAG: LazyFragment 2 onCreateView
    2022-08-28 13:50:00.439 12677-12677/com.lay.image_process E/TAG: LazyFragment 3 onCreate
    2022-08-28 13:50:00.440 12677-12677/com.lay.image_process E/TAG: LazyFragment 3 onCreateView
    2022-08-28 13:50:01.344 12677-12677/com.lay.image_process E/TAG: LazyFragment 4 onCreate
    2022-08-28 13:50:01.345 12677-12677/com.lay.image_process E/TAG: LazyFragment 4 onCreateView
    2022-08-28 13:50:03.315 12677-12677/com.lay.image_process E/TAG: LazyFragment 1 onCreateView

    首先我們先看下,Adapter重建Fragment的時候的核心代碼

    public Object instantiateItem(@NonNull ViewGroup container, int position) {
        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }
    
        final long itemId = getItemId(position);
    
        // Do we already have this fragment?
        String name = makeFragmentName(container.getId(), itemId);
        Fragment fragment = mFragmentManager.findFragmentByTag(name);
        if (fragment != null) {
            if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
            mCurTransaction.attach(fragment);
        } else {
            fragment = getItem(position);
            if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
            mCurTransaction.add(container.getId(), fragment,
                    makeFragmentName(container.getId(), itemId));
        }
        if (fragment != mCurrentPrimaryItem) {
            fragment.setMenuVisibility(false);
            if (mBehavior == BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
                mCurTransaction.setMaxLifecycle(fragment, Lifecycle.State.STARTED);
            } else {
                //關鍵代碼
                fragment.setUserVisibleHint(false);
            }
        }
    
        return fragment;
    }

    我們可以看到,當前Fragment如果被創建但是沒有在當前頁面展示的時候,調用了fragment.setUserVisibleHint(false),也就是說setUserVisibleHint能夠監聽當前Fragment是否可見

    所以我們對Fragment進行改造:

    class LazyFragment(val index:Int) : Fragment() {
    
        //判斷當前頁面是否可見
        private var isShow = false
        //判斷頁面是否創建成功
        private var isViewCreated = false
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            Log.e("TAG","LazyFragment $index onCreate")
        }
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            Log.e("TAG","LazyFragment $index onCreateView")
            return inflater.inflate(R.layout.fragment_lazy, container, false)
        }
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            isViewCreated = true
            lazyLoad()
        }
        override fun setUserVisibleHint(isVisibleToUser: Boolean) {
            super.setUserVisibleHint(isVisibleToUser)
            Log.e("TAG","LazyFragment $index isVisibleToUser $isVisibleToUser")
            if(isVisibleToUser){
                isShow = true
                //才有資格去懶加載
                lazyLoad()
            }else{
                isShow = false
            }
        }
        private fun lazyLoad() {
            if(isViewCreated && isShow){
                Log.e("TAG","Fragment $index loadData")
            }
        }
        override fun onDestroy() {
            super.onDestroy()
            isViewCreated = false
            isShow = false
        }
    }

    如果按照之前的方式,當調用onViewCreated方法的時候,我們就會加載數據;做了懶加載處理之后,重寫了setUserVisibleHint方法,當前頁面可見的時候,才有資格去加載數據,這樣即便創建了Fragment,但是如果不可見就不會加載數據

    2022-08-28 14:06:29.776 25904-25904/com.lay.image_process E/TAG: LazyFragment 0 isVisibleToUser false
    2022-08-28 14:06:29.776 25904-25904/com.lay.image_process E/TAG: LazyFragment 1 isVisibleToUser false
    2022-08-28 14:06:29.776 25904-25904/com.lay.image_process E/TAG: LazyFragment 0 isVisibleToUser true
    2022-08-28 14:06:29.782 25904-25904/com.lay.image_process E/TAG: LazyFragment 0 onCreate
    2022-08-28 14:06:29.783 25904-25904/com.lay.image_process E/TAG: LazyFragment 0 onCreateView
    2022-08-28 14:06:29.796 25904-25904/com.lay.image_process E/TAG: Fragment 0 loadData
    2022-08-28 14:06:29.805 25904-25904/com.lay.image_process E/TAG: LazyFragment 1 onCreate
    2022-08-28 14:06:29.805 25904-25904/com.lay.image_process E/TAG: LazyFragment 1 onCreateView
    2022-08-28 14:06:59.395 25904-25904/com.lay.image_process E/TAG: LazyFragment 2 isVisibleToUser false
    2022-08-28 14:06:59.396 25904-25904/com.lay.image_process E/TAG: LazyFragment 0 isVisibleToUser false
    2022-08-28 14:06:59.396 25904-25904/com.lay.image_process E/TAG: LazyFragment 1 isVisibleToUser true
    2022-08-28 14:06:59.396 25904-25904/com.lay.image_process E/TAG: Fragment 1 loadData
    2022-08-28 14:06:59.399 25904-25904/com.lay.image_process E/TAG: LazyFragment 2 onCreate
    2022-08-28 14:06:59.400 25904-25904/com.lay.image_process E/TAG: LazyFragment 2 onCreateView

    通過日志我們可以看到,當首次進入的時候,雖然Fragment 1 被創建了,但是并沒有加載數據。

    這里有個問題,既然可見之后就能加載數據,那么我只在setUserVisibleHint的時候,判斷是否可見來去加載數據?

    其實是不可以的,通過日志我們能夠發現,setUserVisibleHint是早于onCreate方法調用的,也就是說在頁面還沒有創建時,去加載數據有可能導致頁面元素找不到發生空指針異常。

    2 ViewPager2與ViewPager的區別

    上一小節,我們介紹了ViewPager的加載機制和緩存機制,那么我們把整套頁面搬過來,唯一發生變化的就是將ViewPager轉換為ViewPager2

    class MainLazyLoadAdapter2(
        activity: FragmentActivity,
        val fragments: MutableList<Fragment>
    ) : FragmentStateAdapter(activity) {
        override fun getItemCount(): Int {
            return fragments.size
        }
        override fun createFragment(position: Int): Fragment {
            return fragments[position]
        }
    
    }

    ViewPager2的適配器使用的是FragmentStateAdapter,因為FragmentStateAdapter繼承了RecyclerView.Adapter,因此支持了橫向滑動和豎向滑動

    val fragments = mutableListOf<Fragment>()
    for (index in 0..5) {
        fragments.add(LazyFragment(index))
    }
    vp_lazy_load = findViewById(R.id.vp_lazy_load)
    vp_lazy_load.adapter = MainLazyLoadAdapter2(this, fragments)

    用同樣的方式設置了適配器,我們看下日志輸出,就會發現,咦?怎么跟ViewPager不一樣了

    2022-08-28 14:47:11.790 15514-15514/com.lay.image_process E/TAG: LazyFragment 0 onCreate
    2022-08-28 14:47:11.792 15514-15514/com.lay.image_process E/TAG: LazyFragment 0 onCreateView

    剛進來的時候,只有Fragment 1 加載了頁面,并沒有新建緩存頁面,當我滑動到下一頁的時候,也只有下一頁的頁面進行了重建

    2022-08-28 14:47:11.790 15514-15514/com.lay.image_process E/TAG: LazyFragment 0 onCreate
    2022-08-28 14:47:11.792 15514-15514/com.lay.image_process E/TAG: LazyFragment 0 onCreateView
    2022-08-28 14:47:13.948 15514-15514/com.lay.image_process E/TAG: LazyFragment 1 onCreate
    2022-08-28 14:47:13.948 15514-15514/com.lay.image_process E/TAG: LazyFragment 1 onCreateView

    ViewPager2沒有預加載機制嗎?這里我們就需要看源碼了,直接奔向setOffscreenPageLimit方法,我們看到跟ViewPager的setOffscreenPageLimit方法是不一樣的

    public void setOffscreenPageLimit(@OffscreenPageLimit int limit) {
        if (limit < 1 && limit != OFFSCREEN_PAGE_LIMIT_DEFAULT) {
            throw new IllegalArgumentException(
                    "Offscreen page limit must be OFFSCREEN_PAGE_LIMIT_DEFAULT or a number > 0");
        }
        mOffscreenPageLimit = limit;
        // Trigger layout so prefetch happens through getExtraLayoutSize()
        mRecyclerView.requestLayout();
    }
    public static final int OFFSCREEN_PAGE_LIMIT_DEFAULT = -1;

    這里的判斷條件 limit < 1 && limit != OFFSCREEN_PAGE_LIMIT_DEFAULT,有一個數值能夠通過,就是-1,這就意味著,ViewPager2默認是不支持預加載的

    但是ViewPager2的緩存策略還是存在,因為繼承了RecyclerView的Adapter,所以緩存復用機制是跟RecyclerView一致的,默認mViewCaches緩存池的大小是3

    2022-08-28 15:30:00.579 15514-15514/com.lay.image_process E/TAG: LazyFragment 0 onCreate
    2022-08-28 15:30:00.579 15514-15514/com.lay.image_process E/TAG: LazyFragment 0 onCreateView
    2022-08-28 15:30:03.883 15514-15514/com.lay.image_process E/TAG: LazyFragment 1 onCreate
    2022-08-28 15:30:03.884 15514-15514/com.lay.image_process E/TAG: LazyFragment 1 onCreateView
    2022-08-28 15:30:05.064 15514-15514/com.lay.image_process E/TAG: LazyFragment 2 onCreate
    2022-08-28 15:30:05.064 15514-15514/com.lay.image_process E/TAG: LazyFragment 2 onCreateView
    2022-08-28 15:30:08.997 15514-15514/com.lay.image_process E/TAG: LazyFragment 3 onCreate
    2022-08-28 15:30:08.997 15514-15514/com.lay.image_process E/TAG: LazyFragment 3 onCreateView
    2022-08-28 15:30:20.005 15514-15514/com.lay.image_process E/TAG: LazyFragment 0 onCreate
    2022-08-28 15:30:20.005 15514-15514/com.lay.image_process E/TAG: LazyFragment 0 onCreateView

    當我們滑動到第4個Fragment的時候,注意這里跟ViewPager不一樣的是,ViewPager的緩存是緩存當前頁的左右兩邊,但是ViewPager2就是RecyclerView的緩存機制,順序緩存;

    當滑動到第4個Fragment的時候,因為緩存池大小為3,因此LazyFragment 0 就會從緩存池中移除,當再次滑動到LazyFragment 0的時候,就會重建!

    所以當我們還在思考如何針對ViewPager的預加載機制做懶加載操作時,請將項目中的ViewPager遷移至ViewPager2

    附錄:

    當你的項目中還在使用ViewPager時,建議使用當前這個懶加載框架

    abstract class BaseLazyFragment<VM : ViewModel, VB : ViewBinding> : Fragment() {
        private lateinit var viewModel: VM
        private lateinit var binding: VB
    
        private var isShow = false
        private var isViewCreated = false
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            viewModel = getViewModelInstance()
            binding = getLayoutInflate(layoutInflater)
        }
    
        override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            return binding.root
        }
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            initView()
            isViewCreated = true
            lazyLoad()
        }
        override fun setUserVisibleHint(isVisibleToUser: Boolean) {
            super.setUserVisibleHint(isVisibleToUser)
            if (isVisibleToUser) {
                isShow = true
                lazyLoad()
            } else {
                isShow = false
            }
        }
        override fun onDestroy() {
            super.onDestroy()
            isShow = false
            isViewCreated = false
        }
        private fun lazyLoad() {
            if (isShow && isViewCreated) {
                initData()
            }
        }
        open fun initData() {}
        open fun initView() {}
        abstract fun getViewModelInstance(): VM
        abstract fun getLayoutInflate(layoutInflater: LayoutInflater): VB
    }

    使用方式:

    class LazyFragment(val index:Int) : BaseLazyFragment<MainVM,FragmentLazy2Binding>() {
        override fun initData() {
            super.initData()
            Log.e("TAG","LazyFragment $index initData -- ")
        }
        override fun getViewModelInstance(): MainVM {
            return MainVM()
        }
        override fun getLayoutInflate(layoutInflater: LayoutInflater): FragmentLazy2Binding {
            return FragmentLazy2Binding.inflate(layoutInflater)
        }
    }

    關于“Android性能優化之ViewPagers+Fragment緩存優化怎么實現”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    秦皇岛市| 霍林郭勒市| 安新县| 剑河县| 四川省| 通城县| 西平县| 右玉县| 隆德县| 商河县| 萝北县| 措美县| 依安县| 嘉鱼县| 麻栗坡县| 上犹县| 景洪市| 太谷县| 名山县| 海原县| 张北县| 贺州市| 兴义市| 巴青县| 碌曲县| 彝良县| 连云港市| 安丘市| 营山县| 从化市| 醴陵市| 邹城市| 漳平市| 精河县| 富顺县| 黑山县| 西安市| 新沂市| 广汉市| 曲麻莱县| 临桂县|