【Android】在Activity頁面中如何實現Fragment資料的緩載入

七號座先生發表於2017-12-21

簡述:

漸漸的在開發道路上更注重App的效能, 資料的預載入的處理。在日常開發APP,一個Activity裡面有可能會是有Viewpager與多個Fragment來進行組合,而如果每個Fragment都需要通過網路載入資料,或載入本地快取。 如果當前Activity建立的時候就需要初始化大量的資源,需要網路載入,從伺服器loding。這樣的結果,我們也不會同意。那如何才能更好的處理這個問題呢? 那就需要我們開發人員自定義實現Fragment資料的緩載入。

答案:在Fragment裡的setUserVisibleHint這個方法裡.

該方法用於告訴系統,這個Fragment的UI是否是可見的。所以我們只需要繼承Fragment並重寫該方法,即可實現在fragment可見時才進行資料載入操作,即Fragment的懶載入。

public abstract class LazyFragment extends Fragment {  
    protected boolean isVisible;  
    /** 
     * 在這裡實現Fragment資料的緩載入. 
     * @param isVisibleToUser 
     */  
    @Override  
    public void setUserVisibleHint(boolean isVisibleToUser) {  
        super.setUserVisibleHint(isVisibleToUser);  
        if(getUserVisibleHint()) {  
            isVisible = true;  
            onVisible();  
        } else {  
            isVisible = false;  
            onInvisible();  
        }  
    }  
  
    protected void onVisible(){  
        lazyLoad();  
    }  
  
    protected abstract void lazyLoad();  
  
    protected void onInvisible(){}  
}  

複製程式碼

在LazyFragment,我增加了三個方法,一個是onVisiable,即fragment被設定為可見時呼叫,一個是onInvisible,即fragment被設定為不可見時呼叫。另外再寫了一個lazyLoad的抽象方法,該方法在onVisible裡面呼叫。你可能會想,為什麼不在getUserVisibleHint裡面就直接呼叫呢?

我這麼寫是為了程式碼的複用。因為在fragment中,我們還需要建立檢視(onCreateView()方法),可能還需要在它不可見時就進行其他小量的初始化操作(比如初始化需要通過AIDL呼叫的遠端服務)等。而setUserVisibleHint是在onCreateView之前呼叫的,那麼在檢視未初始化的時候,在lazyLoad當中就使用的話,就會有空指標的異常。而把lazyLoad抽離成一個方法,那麼它的子類就可以這樣做:


public class OpenResultFragment extends LazyFragment{  
    // 標誌位,標誌已經初始化完成。  
    private boolean isPrepared;  
  
    @Override  
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {  
        Log.d(LOG_TAG, "onCreateView");  
        View view = inflater.inflate(R.layout.fragment_open_result, container, false);  
        //XXX初始化view的各控制元件  
    isPrepared = true;  
        lazyLoad();  
        return view;  
    }  
  
    @Override  
    protected void lazyLoad() {  
        if(!isPrepared || !isVisible) {  
            return;  
        }  
        //填充各控制元件的資料  
    }  
  
}  
複製程式碼

在上面的類當中,我們增加了一個標誌位isPrepared,用於標誌是否初始化完成。然後在我們所需要的初始化操作完成之後呼叫,如上面的例子當中,在初始化view之後,設定 isPrepared為true,同時呼叫lazyLoad()方法。而在lazyLoad()當中,判斷isPrepared和isVisible只要有一個不為true就不往下執行。也就是僅當初始化完成,並且可見的時候才繼續載入,這樣的避免了未初始化完成就使用而帶來的問題。

相關文章