打造一個(gè)高效易用的懶加載BaseFragment

首先感謝KingJA提供的第三方庫LoadSir,項(xiàng)目地址為:https://github.com/KingJA/LoadSir
LoadSir是一個(gè)高效易用沦补,低碳環(huán)保啊央,擴(kuò)展性良好的加載反饋頁管理框架,在加載網(wǎng)絡(luò)或其他數(shù)據(jù)時(shí)候衍锚,根據(jù)需求切換狀態(tài)頁面, 可添加自定義狀態(tài)頁面嗤堰,如加載中戴质,加載失敗,無數(shù)據(jù)梁棠,網(wǎng)絡(luò)超時(shí)置森,如占位圖,登錄失效等常用頁面符糊≠旌#可配合網(wǎng)絡(luò)加載框架,結(jié)合返回 狀態(tài)碼男娄,錯(cuò)誤碼行贪,數(shù)據(jù)進(jìn)行狀態(tài)頁自動(dòng)切換漾稀,封裝使用效果更佳。
LoadSir的功能及特點(diǎn)
支持Activity建瘫,F(xiàn)ragment崭捍,F(xiàn)ragment(v4),View狀態(tài)回調(diào)
適配多個(gè)Fragment切換啰脚,及Fragment+ViewPager切換殷蛇,不會(huì)布局疊加或者布局錯(cuò)亂
利用泛型轉(zhuǎn)換輸入信號(hào)和輸出狀態(tài),可根據(jù)網(wǎng)絡(luò)返回體的狀態(tài)碼或者數(shù)據(jù)返回自動(dòng)適配狀態(tài)頁橄浓,實(shí)現(xiàn)全局自動(dòng)狀態(tài)切換
無需修改布局文件
只加載唯一一個(gè)狀態(tài)視圖粒梦,不會(huì)預(yù)加載全部視圖

大致效果如下:

效果

不需要設(shè)置枚舉或者常量狀態(tài)值,直接用狀態(tài)頁類類型(xxx.class)作為狀態(tài)碼
可對(duì)單個(gè)狀態(tài)頁單獨(dú)設(shè)置點(diǎn)擊事件荸实,根據(jù)返回boolean值覆蓋或者結(jié)合OnReloadListener使用匀们,如網(wǎng)絡(luò)錯(cuò)誤可跳轉(zhuǎn)設(shè)置頁
無預(yù)設(shè)頁面,低耦合准给,開發(fā)者隨心配置
可保留標(biāo)題欄(Toolbar,titile view等)
可設(shè)置重新加載點(diǎn)擊事件(OnReloadListener)
可自定義狀態(tài)頁(繼承Callback類)
可在子線程直接切換狀態(tài)
可設(shè)置初始狀態(tài)頁(常用進(jìn)度頁作為初始狀態(tài))
可擴(kuò)展?fàn)顟B(tài)頁面泄朴,在配置中添加自定義狀態(tài)頁
可全局單例配置,也可以單獨(dú)配置
首先我們需要在項(xiàng)目中添加相關(guān)依賴:compile'com.kingja.loadsir:loadsir:1.2.2

第一步:配置
全局配置方式
全局配置方式露氮,使用的是單例模式祖灰,即獲取的配置都是一樣的÷僬蓿可在Application中配置夫植,添加狀態(tài)頁,設(shè)置默認(rèn)狀態(tài)頁

public class MyApp extends Application{
@Override
public void onCreate() {
    super.onCreate();

    LoadSir.beginBuilder().addCallback(new ErrorCallback())
            .addCallback(new EmptyCallback())
            .addCallback(new LoadingCallback())
            .addCallback(new TimeoutCallback())
            .addCallback(new CustomCallback())
            .setDefaultCallback(LoadingCallback.class)
            .commit();

}}

單獨(dú)配置方式
如果你即想保留全局配置油讯,又想在某個(gè)特殊頁面加點(diǎn)不同的配置详民,可采用該方式。

LoadSir loadSir = new LoadSir.Builder()
            .addCallback(new LoadingCallback())
            .addCallback(new EmptyCallback())
            .addCallback(new ErrorCallback())
            .build();
    loadService = loadSir.register(this, new Callback.OnReloadListener() {
        @Override
        public void onReload(View v) {
            // 重新加載邏輯
        }
    });

第二步:注冊(cè)
在Activity中使用

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_content);
// Your can change the callback on sub thread directly.
LoadService loadService = LoadSir.getDefault().register(this, new Callback.OnReloadListener() {
    @Override
    public void onReload(View v) {
        // 重新加載邏輯
    }
});}}

這里需要注意陌兑,register中有兩個(gè)參數(shù)沈跨,這里看第一個(gè)參數(shù),第一個(gè)為Object兔综,通常我們這里是我們要展示狀態(tài)視圖的View饿凛。

         @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable    Bundle savedInstanceState) {

    mRootView = inflater.inflate(setLayoutId(), container, false);
    initView();
    mBaseLoadService = LoadSir.getDefault().register(mRootView, new Callback.OnReloadListener() {
        @Override
        public void onReload(View v) {

            onNetReload(v);

        }
    });
    return mBaseLoadService.getLoadLayout();
}

當(dāng)然,我們也可以是指定的某個(gè)View软驰,假設(shè)在Fragment中只有某個(gè)控件是需要獲取數(shù)據(jù)涧窒,并且該控件并沒有占滿整個(gè)布局,那么我們也可以把第一個(gè)參數(shù)設(shè)置為指定的控件锭亏。

ImageView imageView = (ImageView) findViewById(R.id.iv_img);
LoadSir loadSir = new LoadSir.Builder()
    .addCallback(new TimeoutCallback())
    .setDefaultCallback(LoadingCallback.class)
    .build();
loadService = loadSir.register(imageView, new Callback.OnReloadListener() {
@Override
public void onReload(View v) {
    loadService.showCallback(LoadingCallback.class);
    // 重新加載邏輯
}});

使用還是非常簡單的纠吴,這里需要注意,我們所有的CallBack都是自定義的慧瘤,所有的狀態(tài)視圖都由我們自己來定義戴已,只需要繼承CallBack固该,重寫onCreateView方法即可。

加載中callBack

public class LoadingCallback extends Callback {

@Override
protected int onCreateView() {
    return R.layout.layout_loading }}

超時(shí)CallBack

public class TimeoutCallback extends Callback {

@Override
protected int onCreateView() {
    return R.layout.layout_timeout;
}

@Override
protected boolean onRetry(Context context, View view) {
    Toast.makeText(context.getApplicationContext(),"Connecting to the network again!",Toast.LENGTH_SHORT).show();
    return false;
}}

出錯(cuò)callBack

 public class ErrorCallback extends Callback {
@Override
protected int onCreateView() {
    return R.layout.layout_error;
}}

無數(shù)據(jù)CallBack:

  public class EmptyCallback extends Callback {

@Override
protected int onCreateView() {
    return R.layout.layout_empty;
}}

自定義CallBack:

public class CustomCallback extends Callback {

@Override
protected int onCreateView() {
    return R.layout.layout_custom;
}

@Override
protected boolean onRetry(final Context context, View view) {
    Toast.makeText(context.getApplicationContext(), "Hello buddy, how r u! :p", Toast.LENGTH_SHORT).show();
    (view.findViewById(R.id.iv_gift)).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Toast.makeText(context.getApplicationContext(), "It's your gift! :p", Toast.LENGTH_SHORT).show();
        }
    });
    return true;
}}

知道了如何使用LoadSir之后糖儡,我們就要將它構(gòu)建到我們的基類BaseFragment當(dāng)中了伐坏。

為了避免重復(fù)創(chuàng)建Fragment,以及數(shù)據(jù)的重復(fù)加載握联,我們通常會(huì)使用懶加載方式來解決這一問題桦沉。這里我就直接貼代碼了,注釋得非常清楚金闽,無非就是判斷當(dāng)然Fragment是否可見永部,可見的話并且是第一次才加載數(shù)據(jù)。

public abstract class BaseFragment extends Fragment{

public Context mContext;
protected View mRootView;
protected LoadService mBaseLoadService;
/**
 * 是否為可見狀態(tài)
 */
private boolean isVisible;

/**
 * 是否視圖加載完成(第一次加載)
 */
private boolean isPrepared;

/**
 * Fragment生命周期中呐矾,在執(zhí)行完onAttach之后就可以獲取到上下文了
 * @param savedInstanceState
 */
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mContext = getActivity();
}


@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

    mRootView = inflater.inflate(setLayoutId(), container, false);
    initView();
    mBaseLoadService = LoadSir.getDefault().register(mRootView, new Callback.OnReloadListener() {
        @Override
        public void onReload(View v) {

            onNetReload(v);

        }
    });
    return mBaseLoadService.getLoadLayout();
}


@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    isPrepared = true;
    lazyLoad();
}

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    //如果可見
    if (getUserVisibleHint()){
        isVisible = true;
        onVisible();
    }else {
        isVisible = false;
        onInvisible();
    }
}

/**
 *可見做懶加載
 */
private void onVisible(){
    lazyLoad();
}

private void lazyLoad(){
    if (!isVisible || !isPrepared){
        return;
    }
    initData();
    isPrepared = false;
}

/**
 * 不可見時(shí)做一些銷毀操作
 */
protected void onInvisible(){}

/**
 * 初始化控件
 */
public abstract void initView();

/**
 * 綁定布局
 */
protected abstract int setLayoutId();

/**
 * 初始化數(shù)據(jù)
 */
protected abstract void initData();

/**
 * 重新加載
 * @param v
 */
protected abstract void onNetReload(View v);}

基類還是非常簡單的,我們可以根據(jù)自己的業(yè)務(wù)需求自行拓展懦砂,比如加入Toast等蜒犯。
那么我們Fragment中的代碼就非常簡單了,為了更好的展示效果荞膘,我們?cè)诔跏蓟瘮?shù)據(jù)時(shí)罚随,模擬網(wǎng)絡(luò)請(qǐng)求失敗,在onNetReload方法中模擬請(qǐng)求成功羽资。

public class OneFragment extends BaseFragment {


@Override
public void initView() {

}

@Override
protected int setLayoutId() {
    return R.layout.view1;
}

@Override
protected void initData() {

    PostUtil.postCallbackDelayed(mBaseLoadService, ErrorCallback.class);
}

@Override
protected void onNetReload(View v) {
    Toast.makeText(getContext(),"reload in Fragment A",Toast.LENGTH_SHORT).show();
    mBaseLoadService.showCallback(LoadingCallback.class);
    PostUtil.postSuccessDelayed(mBaseLoadService);
}}

本文到此基本可以結(jié)束了淘菩,畢竟標(biāo)題是BaseFragment,再說就跑題了M郎3备摹!至于TabLayoyut和ViewPager結(jié)合Fragment的使用我這里就不介紹了腹暖。

這里把文章中設(shè)計(jì)到的一些資源文件放出來給大家汇在。

timeout.png
custom.png
empty.png
img.jpg
music.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市脏答,隨后出現(xiàn)的幾起案子糕殉,更是在濱河造成了極大的恐慌,老刑警劉巖殖告,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件阿蝶,死亡現(xiàn)場離奇詭異,居然都是意外死亡黄绩,警方通過查閱死者的電腦和手機(jī)羡洁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宝与,“玉大人焚廊,你說我怎么就攤上這事冶匹。” “怎么了咆瘟?”我有些...
    開封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵嚼隘,是天一觀的道長。 經(jīng)常有香客問我袒餐,道長飞蛹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任灸眼,我火速辦了婚禮卧檐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘焰宣。我一直安慰自己霉囚,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開白布匕积。 她就那樣靜靜地躺著盈罐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪闪唆。 梳的紋絲不亂的頭發(fā)上盅粪,一...
    開封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音悄蕾,去河邊找鬼票顾。 笑死,一個(gè)胖子當(dāng)著我的面吹牛帆调,可吹牛的內(nèi)容都是我干的奠骄。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼番刊,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼戚揭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起撵枢,我...
    開封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤民晒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后锄禽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體潜必,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年沃但,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了磁滚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖垂攘,靈堂內(nèi)的尸體忽然破棺而出维雇,到底是詐尸還是另有隱情,我是刑警寧澤晒他,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布吱型,位于F島的核電站,受9級(jí)特大地震影響陨仅,放射性物質(zhì)發(fā)生泄漏津滞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一灼伤、第九天 我趴在偏房一處隱蔽的房頂上張望触徐。 院中可真熱鬧,春花似錦狐赡、人聲如沸撞鹉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽孔祸。三九已至,卻和暖如春发皿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拂蝎。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來泰國打工穴墅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人温自。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓玄货,卻偏偏與公主長得像,于是被迫代替她去往敵國和親悼泌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子松捉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,262評(píng)論 25 707
  • LoadSir是一個(gè)高效易用隘世,低碳環(huán)保,擴(kuò)展性良好的加載反饋頁管理框架鸠踪,在加載網(wǎng)絡(luò)或其他數(shù)據(jù)時(shí)候丙者,根據(jù)需求切換狀態(tài)...
    KingJA閱讀 15,748評(píng)論 69 125
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)营密,斷路器械媒,智...
    卡卡羅2017閱讀 134,693評(píng)論 18 139
  • 作者介紹馮宇飛 ,現(xiàn)任人人車Android客戶端架構(gòu)師。 本文回顧總結(jié)了人人車公司Android客戶端的架構(gòu)演進(jìn)歷...
    passiontim閱讀 1,545評(píng)論 0 9
  • 終于考完了計(jì)算機(jī),算是了卻了一件大事主儡。姑娘松口氣奖唯,然后繼續(xù)努力。為了成為更優(yōu)秀的自己缀辩。
    9a63a67e192b閱讀 53評(píng)論 0 1