首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android ViewPager 動態增減頁面:PagerAdapter 正確實現與 notifyDataSetChanged

     編輯:程式設計綜合問答

問題現象

需動態增減 ViewPager 頁面,自定義 PagerAdapter 需正確實現 instantiateItem、destroyItem、getCount、isViewFromObject,並處理資料變更通知。

核心 PagerAdapter 實現


class DynamicPagerAdapter extends PagerAdapter {
    private final List views = new ArrayList<>();
    
    // 新增頁面
    public void addView(View view, int position) {
        views.add(position, view);
        notifyDataSetChanged();  // 關鍵:通知 ViewPager 重新查詢 getCount/instantiateItem
    }
    
    // 移除頁面
    public void removeView(int position) {
        views.remove(position);
        notifyDataSetChanged();
    }
    
    @Override
    public int getCount() {
        return views.size();
    }
    
    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;  // View 本身即 Object
    }
    
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        View view = views.get(position);
        container.addView(view);
        return view;  // 返回 View 作為 Object
    }
    
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((View) object);
    }
    
    // 可選:獲取頁面標題
    @Override
    public CharSequence getPageTitle(int position) {
        return "Page " + (position + 1);
    }
}

關鍵方法解析

方法職責關鍵點
instantiateItem建立/回收頁面 View 加入容器返回 View 作為 Object,供 isViewFromObject 比對
destroyItem從容器移除頁面接收 instantiateItem 返回的 Object
isViewFromObject判斷 View 是否對應 Object直接比較 reference (view == object)
getCount當前頁面總數動態增減時必須即時反映
notifyDataSetChanged通知資料變更增減頁面後必須調用

ViewPager 佈局參數說明

  • ViewGroup container:即 ViewPager 本身(繼承自 ViewGroup),addView/removeView 直接操作它。
  • 不需手動呼叫 startUpdate/finishUpdate,notifyDataSetChanged 內部處理。

現代替代:FragmentStateAdapter (ViewPager2)


// ViewPager2 + FragmentStateAdapter (推薦新專案)
class ScreenSlideAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {
    private val fragments = mutableListOf()
    
    fun addFragment(fragment: Fragment) {
        fragments.add(fragment)
        notifyItemInserted(fragments.size - 1)
    }
    
    fun removeFragment(position: Int) {
        fragments.removeAt(position)
        notifyItemRemoved(position)
    }
    
    override fun getItemCount() = fragments.size
    override fun createFragment(position: Int) = fragments[position]
}

優勢:Fragment 生命週期自動管理、記憶體優化、支援 RTL、動畫豐富、RecyclerView 底層。

常見坑點

  • 忘記 notifyDataSetChanged:資料變更但 UI 不更新。
  • isViewFromObject 邏輯錯誤:導致頁面閃爍、重複建立、崩潰。
  • instantiateItem 返回非 View 物件:後續 destroyItem 無法正確移除。
  • 大量頁面用 View 版 PagerAdapter:記憶體壓力大,改用 Fragment 版或 ViewPager2。

理解 PagerAdapter 四大核心方法契約與 notifyDataSetChanged 觸發機制,是動態 ViewPager 穩定運作的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved