1. 程式人生 > >ViewPager切換Fragment時ListView資料不更新

ViewPager切換Fragment時ListView資料不更新

問題描述:

開發中常會遇見這樣的場景:用一個ViewPager巢狀多個Fragment來切換頁面展示資料,但是如果Fragment展示的資料是用ListView、GridView、RecyclerView等滑動控制元件來展示的,那麼這樣的Fragment經常會出現白屏,即ListView等控制元件沒有重新整理資料,導致出現白屏。(這個問題很早就出現過,當時做了下筆記,今天無意之間又遇見了,隨手把之前的筆記貼上)

問題分析:

出現這麼的原因一般是我們通常都會對adapter做這樣的判斷:
if (adapter == null) {
            adapter = new BusinessAdapter(R.layout.item_business, businessList);
            mIView.initAdapter(adapter);
        } else {
            adapter.notifyDataSetChanged();
        }

只有adapter不為null時,我們new一個adapter,同時會在構造方法中傳遞一個數據集合,這個資料集合會同adapter 進行資料的繫結,在載入更多資料的時候不在newadapter,而是notifyDataSetChanged,需要注意的時候,呼叫notifyDataSetChangednotifyDataSetChanged重新整理資料,必須保證在newadapter時傳入的集合是同一個集合,否則會出現adapter中的資料為空,導致白屏出現。

產生問題的具體程式碼:

看一下我產生這個問題的場景、程式碼以及對問題的再次分析: ViewPager中有6個Fragment,其中兩個是用RecyclerView來展示資料的,這兩個Fragment我都是在onActivityCreate()方法中呼叫網路請求,獲取完資料後對資料進行了整理,存放到了集合中,之後呼叫了initAdapter()方法,在這個方法中new 了adapter,然後讓RecyclerView與adapter進行繫結:
@Override
    public void onSucess(Object data, int page, String type) {
        // 獲取完資料後對資料進行整理
        BusinessBean businessBean = (BusinessBean) data;
        List<BusinessBean.BusinessDetails> businessInfo = businessBean.getSjinfo();
        if (businessInfo.size() != 0) {
            if (page == 1) businessList.clear();
            businessList.addAll(businessInfo);
        }
        changeLayout(businessList.size());
        initBusinessAdapter();//呼叫建立adapter的方法
    }
initBusinessAdapter的方法如下:
private void initBusinessAdapter() {
        if (adapter == null) {
            adapter = new BusinessAdapter(R.layout.item_business, businessList);
            mIView.initAdapter(adapter);//RecyclerView和adapter進行繫結
        } else {
            adapter.notifyDataSetChanged();
        }
    }
在第一次切換到這兩個頁面時資料顯示是沒有問題的,但是切換到其他頁面再次切換回來時發現Fragment為白屏。 那就通過程式碼試一下問題的原因: 我們先把判斷adapter是否為空的程式碼去掉,每次進入頁面或者通過上下啦重新整理更多資料都重新new adapter,測試一下發現,不管如何切換ViewPager的頁面,fragment都不會再白屏了,但是問題是每次下拉重新整理和上啦載入都要new一個新的adapter,太不合理了。而且在我們重新newadapter時就不會出現白屏,說明在之前的程式碼中重新切換到該Fragment時,執行的是adapter != null下面的notifyDataSetChanged方法,通過列印日誌我們看一下是否是這樣:
private void initBusinessAdapter() {
        if (adapter == null) {
            Logger.e("notifydata--busi1 =" + businessList.size());
            adapter = new BusinessAdapter(R.layout.item_business, businessList);
            mIView.initAdapter(adapter);
        } else {notifyDataSetChanged
            Logger.e("notifydata--busi2 = " + businessList.size());
            adapter.notifyDataSetChanged();
        }
    }
發現確實是走了notify的方法,說明集合可能不一樣,但是集合就是成員變數,沒辦法重新再new一個,那就有可能是ListView和adapter失去了關聯導致的,網上有一種說法是ListView、RecyclerView銷燬了,為null,但是通過實踐打印發現並不為null,所以可能是兩者失去了關聯,如果是這個原因的話,那就每次進入時都關聯一次,在onActivityCreated方法中再次進行關聯:
if (adapter != null) {
recyclerView.setAdapter(adapter);
}
這樣做之後,發現的確沒有問題了。

相關推薦

ViewPager切換FragmentListView資料更新

問題描述: 開發中常會遇見這樣的場景:用一個ViewPager巢狀多個Fragment來切換頁面展示資料,但是如果Fragment展示的資料是用ListView、GridView、RecyclerView等滑動控制元件來展示的,那麼這樣的Fragment經常會出現白屏,即L

使用viewpager+fragment,在activity啟動模式為singleTask,跳轉到當前頁面重新載入資料fragment資料更新

如題,看程式碼: (Activity):         Bundle bundle = new Bundle();         bundle.putString("courseMap", Converter.map2String(courseMap));       

ViewPager中使用Fragment防止資料預載入

  我們知道ViewPager是具有預載入頁面的特性的,預設會提前載入左右各1頁的View, 如果在ViewPager中使用Fragment,那麼Fragment也會被預載入,如果你是在Fragment生命週期中寫請求網路載入資料的方法,就會遇到頁面未展示,但是資料會被提前載入的問題,有時我

(15)關於ListView中notifyDataSetChanged()重新整理資料更新原因

使用Listview的時候: 當要動態顯示更改後的資料(例如資料庫改動), 很多人應該都用過notifyDataSetChanged();這個方法來重新整理Listview,顯示改後的資料. 這時候就要注意了:                  ......       

Android ListView中notifyDataSetChanged()重新整理資料更新原因

使用Listview的時候: 當要動態顯示更改後的資料(例如資料庫改動), 很多人應該都用過notifyDataSetChanged();這個方法來重新整理Listview,顯示改後的資料.這時候就要注意了:                 ......                 private Ar

解決ViewPager展示Fragment重新設定setAdapter會重置Fragment的bug

用過ListView和RecycleView的人都知道不管當前列表的瀏覽記錄在哪裡,只要重新setAdapter,列表就會重置,即從第一條item開始顯示. 因此,想當然的我也就認為ViewPager也是這個樣子的.結果並不是我想的那麼簡單,重複setAdapter並沒什麼卵用,Frag

ListView notifyDataSetChanged起作用 資料更新的原因

 在動態重新整理ListView時,使用notifyDataSetChanged並沒有起到作用。有時會被困擾得很痛苦。 其實,在使用notifyDataSetChanged過程中,還是有細節需要注意的。舉個例子: 我的ListView使用的資料來源是來自ArrayLis

解決使用GPU處理影象提示資料能是gpuArray的問題

【時間】2018.10.11 【題目】解決使用GPU處理影象時提示資料不能是gpuArray的問題   【問題描述】今天我在MATLAB中,用GPU進行影象處理,最後想用imwrite儲存下來,但出現了以下錯誤:錯誤使用 imwrite  需要的 DATA 應為以下型

echarts 資料更新

 這幾天在用echarts折線圖的時候,當第一次載入的資料條目數大於之後載入的條目數的時候出現了一個奇怪的bug, 第二次載入的資料覆蓋等量的第一次的資料。第一次載入多餘的資料不會丟失,還會展示在折線圖上。 此時,我到echarts中的option的資料legend和se

在同一個Activity下實現切換Fragment重新整理fragment介面

在做專案時遇到一個問題,我在A fragment中展示從伺服器拿到的資料,在B fragment,新增資料到伺服器,同時B fragment同步重新整理,糾結了很久都不行,因為我建立fragment時用的是:show與hide switch (index) {

從一個Activity返回一個Activity 或Fragment回傳資料

在當前Activity或Fragment利用 Intent intent = new Intent(LoginActivity.this,MainActivity.class); intent.putExtra("name”,"value”);(此處沒有用到) startActivityForR

vue 物件陣列的值更改後,資料更新的解決辦法

this.$set(this.list[index],  'show', value) 注意: 這樣賦值需要在第一次更改(除宣告外)this.list[index].show的時候就用$set,若是之前就直接賦值,後面再用$set不會生效。

vue路由跳轉資料更新解決

第二次進入頁面,頁面路由引數已經改變,但是頁面內容不會重新整理。 問題原因:在元件mounted鉤子中呼叫的重新整理頁面內容,但測試發現這個鉤子沒有被呼叫。後來發現App.vue中使用了<keep-alive>: <template> <div id="

ViewPager切換Fragment生命週期變化

很久沒有寫部落格了,今天學習了MD的TabLayout ,使用到了ViewPager,於是對於很久以來的一個疑問:ViewPager切換Fragment生命週期是如何變化的進行了一個測試。 本文研究了: 1. ViewPager2個相鄰Fragment之間的

vue ajax請求資料更新 解決方案

這個問題  卡我好久, 找到方法了,分享出來吧 舉個簡單例子 <template> <div> {{a}} </div> </templ

IE瀏覽器下AJAX快取問題導致資料更新的解決辦法

描述 做專案時遇到的問題: 通過AJAX請求後臺時,當引數相同,IE瀏覽器會從快取中取值而非從重新請求伺服器。其他使用非IE核心的瀏覽器並無此問題。 解決 有兩種解決辦法; 其一: 在AJAX請求

angularJS變數變化頁面檢視更新問題

頁面檢視不更新時,在方法後手動呼叫$scope.$apply()方法,手動更新檢視 舉例如下: else if(count==1){ $scope.showImg=dataBase64;strHead=dataBase64.indexOf('data:image/');st

關於viewpagerfragment需要重新整理資料的bug,解決辦法。

       首先要解析兩個問題,第一:在 Fragment 中,使用 getArguments() 來取得引數。這是常用的引數傳遞方式。這種資料傳遞方式只可能用一次,在 Fragment 被新增到 FragmentManager 後,所以會造成,就算我們把fragment釋放掉,在viewpager裡面,f

android 改變ViewPager切換頁面的速度

宣告:引自http://zhidao.baidu.com/link?url=9YCi4uGUki-xgV6d8_ZN5N1Jq9-eRw4efaiwvC6_aehw62IoskmrrS1ew1Cm11UmTO4UNMoaZEN6DI1HUedTLJA8Kt1-v0lWMCW

完美 解決fragmentlistview資料丟失問題和問題分析

public class MainpageFind extends Fragment  {     private ListViewForScrollView mListview;     private FindShareAdatpter shareAdatpter = null;     privat