日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

谷歌电子市场开发流程(3)-关于加载界面的处理

發布時間:2024/8/1 编程问答 54 豆豆
生活随笔 收集整理的這篇文章主要介紹了 谷歌电子市场开发流程(3)-关于加载界面的处理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

上一篇說到谷歌電子市場app的大體框架,重點是怎樣填充viewpager,我們使用了一個個Fragment去作為頁面的載體,這篇我們將怎樣在Fragment中初始化頁面。

我們知道,Fragment只是一個View的載體,也就是說View是顯示在Fragment中,所以,初始化一個Fragment需要實現onCreateView()方法,返回的View就是顯示在Fragment中的頁面,因此,我們要編輯一個個的View來作為onCreateView()方法的返回值,而此項目中包含的7個標簽頁Fragment都是繼承BaseFragment,為什么要這么做呢?我們可以用面向對象的思想來思考,上篇提到過,各個標簽頁顯示的View有相似之處。在對網絡發出請求時,根據網絡狀態,頁面會顯示不同的狀態。

1.未加載和沒有數據狀態。

2.加載失敗

3.正在加載

4.加載成功

大致分為五種狀態(未加載和沒有數據顯示相同界面),其中只有加載成功之后頁面才會顯示從網絡中獲取到的數據,而其他四種狀態各個頁面顯示的都是相同的View,這就是相似之處,而共同之處可以的父類就進行初始化,子類只需直接繼承即可。因此在BaseFragment中,我們可以直接自定義一個View類,去填充它。接下來問題就是,該自定義一個什么View才合適呢?

在開發其他app時,每個Activity幾乎都會為它配置一個相應的Layout文件,也就是顯示在Activity中的界面,更直白的說,就是填充在Activity中的View,而Layout文件就是布局文件,我們知道,android中有五大布局,LinerLayout(線性布局)、FrameLayout(幀布局)、TableLayout(表格布局)、RelativeLayout(相對布局)、AbsoluteLayout(絕對布局),其中幀布局是五大布局中最簡單的一個布局,在這個布局中,整個界面被當成一塊空白備用區域,這正是我們需要的,也就相當于在Fragment中放了一塊空白的畫布,我們只需要在上面畫出我們所需要界面效果即可。因此,自定義View可以繼承FrameLayout。

新建Loadingpage類,繼承FrameLayout,實現三個構造方法。然后在BaseFragment初始化一個LoadingPage對象,將其作為onCreateView()的返回值。

現在畫布有了,我們就要開始動手繪畫了。

1.考慮到網絡加載的五種狀態,首先設置一些代表這些狀態的標記常量

private static final int STATE_LOAD_UNDO=1;//未加載 private static final int STATE_LOAD_LOADING=2;//加載中 private static final int STATE_LOAD_ERROR=3;//加載失敗 private static final int STATE_LOAD_EMPTY=4;//數據為空 private static final int STATE_LOAD_SUCCESS=5;//加載成功

2.開始初始化頁面,上面說過,只有加載成功的頁面沒有相似,其它四種狀態我們都可在此類中初始化

(1)對上述四種狀態編寫相應的布局文件

(2)使用View.inflate()方法,將布局文件轉換為一個個的View

(3)調用addView()方法將View添加到FrameLayout中

運行之后,發現在界面中各個狀態對應的頁面重疊在一起,那么,接下來就需要對各種狀態進行判斷,來判斷何種頁面該顯示和不該顯示。

3.創建一個showRightPage()方法,在此方法中實現判斷邏輯

private void showRightPage() {mLoadingEmptyPage.setVisibility((mCurrentState==STATE_LOAD_UNDO||mCurrentState==STATE_LOAD_EMPTY)?VISIBLE:GONE); mLoadingErrorPage.setVisibility(mCurrentState==STATE_LOAD_ERROR?VISIBLE:GONE); mLoadingPage.setVisibility((mCurrentState == STATE_LOAD_LOADING) ? VISIBLE : GONE); if (mLoadingSuccessPage==null&&mCurrentState==STATE_LOAD_SUCCESS){mLoadingSuccessPage = onCreateSuccessPage(); if (mLoadingSuccessPage!=null){addView(mLoadingSuccessPage); }} }

這個方法主要就是使用View的setVisbility()方法來實現view的顯示和隱藏。

再運行之后,發現運行正常,得到我們想要的效果。

現在,我們需要解決的就是加載成功狀態頁面的初始化,這里邏輯比較繞,需要好好整理思路。

首先,我們知道,每一個Fragment里的加載成功頁面是各不相同的,因此,父類中也就是BaseFragment中不能決定各子類的頁面的顯示效果,換句話說,加載成功頁面不能在父類中初始化,那么,該怎樣讓子類決定該如何加載呢?有沒有一種類,是在父類聲明,而在子類中實現的呢?

沒錯,就是抽象類,面向對象的思想告訴我們,我們可以在抽象類中聲明抽象方法,繼承抽象類的子類必須要實現其父類未實現的抽象方法,這正是我們想要的。

1.將LoadingPage類改為抽象類,在其中添加onCreateSuccessPage()抽象方法,交給其子類實現,因為LoadingPage類不知道該如何初始化加載成功頁面,只能交給其子類去實現。由于BaseFragment中初始化了LoadingPage類的對象,因此,也需要實現其抽象方法。

mLoadingPage = new LoadingPage(UIUtils.getContext()){@Override public View onCreateSuccessPage() {return null; } };

2.但是,此時又出現了問題,BaseFragment也不知道該如何初始化加載成功頁面,所以,我們再將BaseFragment類改為抽象類,創建onCreateSuccessPage()抽象方法,交給各自的標簽Fragment去實現。

mLoadingPage = new LoadingPage(UIUtils.getContext()){@Override public View onCreateSuccessPage() {return BaseFragment.this.onCreateSuccessPage(); } };

現在,我們實現了加載成功頁面的初始化,但是,新的問題又出現了,我們知道,加載成功是需要請求數據的,每個頁面都需要請求數據,這又是相似之處,那么就可以在父類去初始化

1.在LoadingPage類中創建一個LoadingData()方法,因為要請求網絡數據,所以必須開啟子線程去加載,而具體如何加載,請求何種網絡,以什么方式去請求,LoadingPage都不知道,那么就只有交給其他類去實現,所以需要再創建一個onLoad()抽象方法。在這里還要注意onLoad()的返回值。onLoad()需不需要返回值呢?

此時又要考慮到網絡狀態的問題,對于請求數據,可能就有三種情況,第一種是最好的,加載成功了,我們獲取到了數據,頁面正常運行了,第二種呢,就是加載失敗,比如說服務器崩潰了,手機沒聯網,這些情況都可能導致加載失敗,一旦加載失敗,那么就要回到加載失敗狀態的頁面,第三種,就是數據為空的情況,網絡都正常,但是服務器中沒有數據提供,那么請求到的數據也就是空的,那么就必須返回到數據為空的狀態頁面。

既然有網絡狀態的問題,那么,onLoad()方法就必須要有一個返回值,告訴LoadingData()方法到底有沒有接收到數據,以便各個標簽頁顯示相應的加載頁面,因為除了加載成功的頁面,其他兩種狀態的頁面都在LoadingPage類中初始化,而LoadingData()是在LoadingPage類中的,所以onLoad()方法需要返回值。

那么返回值是什么呢?包含多個數據,我們首先想到的就是一個集合去封裝,但是我們又知道,這三種狀態需要和上面五種網絡狀態的標記常量關聯起來,這時,就可以想到使用枚舉是最好的,枚舉中的每一個成員都代表一個對象,我們去實現它的一個帶參的構造方法去覆蓋默認的構造方法,這個參數就可以設置為int型(因為,代表上述五種網絡狀態的標記常量是int型的,我需要將標記常量作為參數去和每一個枚舉成員關聯起來)。

public enum ResultState{STATE_SUCCESS(STATE_LOAD_SUCCESS),STATE_EMPTY(STATE_LOAD_EMPTY),STATE_ERROR(STATE_LOAD_ERROR); private int state; ResultState(int state){this.state=state; }public int getState(){return state; } }

這樣一個onLoad()抽象方法就構造完成了。此時,我們在LoadingData中就可以根據onLoad()的返回值去做相應的UI更新,此處還需要注意,因為LoadingData()方法中單獨開了一個子線程去實現請求網絡數據,而更新UI必須在主線程中實現,這時,UIUtils工具類就體現其作用了,我們在上一篇中就說過,UIUtils中維護了一個RunningMainThread()方法,其作用就是將線程拋給主線程去實現,此處就可以直接調用這個方法,去實現UI更新。

public void LoadingData(){if (mCurrentState!=STATE_LOAD_SUCCESS){mCurrentState=STATE_LOAD_SUCCESS; new Thread(new Runnable() {@Override public void run() {final ResultState resultState=onLoad(); UIUtils.RunningMainThread(new Runnable() {@Override public void run() {if (resultState!=null){mCurrentState=resultState.getState(); }showRightPage(); }}); }}).start(); } }

至此,LoadingData()就已經維護完成。但是,我們也發現這個方法還沒有任何調用,那么,在何處調用這個方法呢?

當我們打開應用時,頁面就開始請求數據,在滑動ViewPager里的頁面時,我們也需要去請求數據,也就是說,當前ViewPager處于哪一個位置,哪一個位置的Fragment里的頁面就要請求數據,所以,我們在MainActivity中,實現onPageChangeListener()監聽器,監聽其中的頁面選擇,在其中的onPageSelector()方法中去調用onLoad()

這就是整個關于加載頁面的處理流程,我們可以看到,在這段邏輯中,大量的使用了封裝,知識面向對象得核心思想,封裝大大簡化了我們的代碼量,但是同時也使代碼的復雜度大大上升了,必須環環相扣,才能做到滴水不漏,使應用運行成功。此處再附上兩張邏輯處理圖幫助自己理解。

ps:終于敲完了,已經凌晨4點。。。不說了,睡覺,明天繼續!!!


總結

以上是生活随笔為你收集整理的谷歌电子市场开发流程(3)-关于加载界面的处理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。