Android MVP升級(jí)路(三)隨心所欲的旗艦版

Android MVP升級(jí)路系列文章目錄:

01 序

  1. 第一、二章中有些類的命名存在筆誤,目前發(fā)現(xiàn)的已糾正。

  2. 如果你有把前兩篇文章認(rèn)真的看完,那么你已經(jīng)基本掌握了MVP架構(gòu)核心思想,可以在實(shí)際開發(fā)項(xiàng)目中使用它了。

  3. 有不少問我要源碼demo的朋友,demo確實(shí)有,前面文章之所以沒留下源碼是因?yàn)槲腋M隳軌蛴H手寫出來一套屬于自己的東西,在這過程中你可以反復(fù)斟酌各層之間的邏輯,包結(jié)構(gòu)以及如何設(shè)計(jì)父類的通用方法。建議還沒手寫過的朋友停下來去寫一套自己的MVP。

  4. 鑒于前面文章已經(jīng)算是MVP的入門,本文主要聊一些實(shí)際使用中架構(gòu)項(xiàng)目時(shí)的思考。

02 Token的有效性

在第二章中我們利用了類似策略模式的方法對(duì)Model層實(shí)現(xiàn)了統(tǒng)一管理,利用Token標(biāo)識(shí)不同的model,可是這樣會(huì)存在一些隱患。

例如當(dāng)我們給一個(gè)已經(jīng)登記在Token中的Model類改了名字,必須同時(shí)去Token中更新手動(dòng)一下對(duì)應(yīng)的字符串。拋開增加維護(hù)成本不說,一旦有一個(gè)類我們忘記手動(dòng)更新,那么它就不能用了。

顯然,意識(shí)到這個(gè)問題后此方法必須立刻優(yōu)化。

放棄Token,直接對(duì)類反射

上一章說道,token其實(shí)就是描述某個(gè)model類“包名+類名”的字符串,有了它我們就可以得到這個(gè)類對(duì)應(yīng)的class對(duì)象,從而實(shí)例化出對(duì)象:
model = (BaseModel)Class.forName(token).newInstance(); // 使用token實(shí)例化對(duì)象

既然token有限制,我們就直接跳過token解析這一步,直接傳遞class對(duì)象:

    public class DataModel {
        public static BaseModel request(Class clazz) {
            // 聲明一個(gè)空的BaseModel
            BaseModel model = null;
            // 判斷class對(duì)象是不是BaseModel的實(shí)例
            if (clazz instanceof BaseModel) {
                try {
                    //利用反射機(jī)制獲得對(duì)應(yīng)Model對(duì)象的引用
                    model = (BaseModel) clazz.newInstance();
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
            return model;
        }
    }

請(qǐng)求數(shù)據(jù)時(shí)直接傳遞model的class對(duì)象即可:

        DataModel
                // 設(shè)置Model
                .request(UserDataModel.class)
                // 添加請(qǐng)求參數(shù),沒有則不添加
                .params(userId)
                // 注冊(cè)監(jiān)聽回調(diào)
                .execute(new UserCallback());

到此我們已經(jīng)解決了token方法中更新類名需要手動(dòng)同步的問題,但是還并不完美。假如一個(gè)項(xiàng)目中有10處位置調(diào)用了同一個(gè)model,當(dāng)這個(gè)model類名有變化時(shí)這10處均發(fā)生了改變,雖然IDE會(huì)自動(dòng)幫我們修改其他地方,但是終究還是發(fā)生了多余的變化。

理想狀態(tài)下,我們希望無論model被多少處調(diào)用,它自身的改變并不會(huì)影響其他地方,那要怎么做呢?方法有很多,比如采用Token<Key,Value>方法映射等等,大家一起想想呀歡迎留言~

03 通用的callback

在數(shù)據(jù)請(qǐng)求中我們需要在callback的各個(gè)回調(diào)中分別取處理對(duì)應(yīng)的請(qǐng)求結(jié)果,但是你只要寫多了就會(huì)發(fā)現(xiàn),除了請(qǐng)求成功的回調(diào)方法,其他的像請(qǐng)求失敗,請(qǐng)求出錯(cuò)這些方法我們做的事幾乎是一樣的。

那既然這樣,我們是不是可以構(gòu)建一個(gè)通用的BaseCallback去處理請(qǐng)求的異常情況呢?

04 鏈接view

在第一章我們封裝了base層后,雖然大大的減少冗余代碼,但是在每個(gè)activity我們都要去手動(dòng)操作presenter與view的鏈接與斷開操作,這顯然不是很美好的。

優(yōu)化的辦法也很簡單,我們都知道每個(gè)activity都繼承于BaseActivity,每個(gè)presenter都繼承于BasePresenter,所以,我們只需要在BaseActivity中實(shí)現(xiàn)BasePresenter鏈接view的操作即可。

在BaseActivity中:

public abstract class BaseActivity extends Activity implements BaseView {

    /**
     * 獲取Presenter實(shí)例,子類實(shí)現(xiàn)
     */
    public abstract BasePresenter getPresenter();

    /**
     * 初始化Presenter的實(shí)例,子類實(shí)現(xiàn)
     */
    public abstract void initPresenter();

    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initPresenter();
        if (getPresenter() != null){
            getPresenter().attachView();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (getPresenter() != null){
            getPresenter().detachView();
        }
    }

    // 下面代碼省略...
}

在具體的Activity中使用:

public class MainActivity extends BaseActivity implements MvpView  {

    // 繼承于BasePresenter
    MvpPresenter presenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    protected BasePresenter getPresenter() {
        return presenter;
    }

    @Override
    protected void initPresenter() {
        presenter = new MvpPresenter();
    }

    // 下面代碼省略...
}

在上面的例子中,我為了更直觀的展示效果設(shè)計(jì)了兩個(gè)抽象方法,分別是初始化和獲取presenter,當(dāng)然其實(shí)完全可以只有一個(gè)獲取presenter方法就行,看自己喜好即可。

05 思想

能讀到這里的朋友相信都是真愛沒錯(cuò)了,不知道朋友你有沒有發(fā)現(xiàn)無論是前兩章講的那么詳細(xì)但是沒給源碼,還是這章的點(diǎn)到為止,我都是在強(qiáng)調(diào)思想要遠(yuǎn)比代碼重要。

其實(shí)MVP本身的代碼,格式什么的并是不那么重要,重要的它的核心思想,以一種什么樣的方式工作的。當(dāng)你完全理解了它的思想,你就可以按照自己的喜好隨意優(yōu)化架構(gòu)。

06 無奈的沒落

回想起大學(xué)那會(huì)剛接觸MVP時(shí)真的被驚艷到了,不同類別的邏輯代碼被劃分的井井有條,可是隨著時(shí)間的慢慢推移,MVP的缺陷也越來越明顯,那就是代碼太過冗余,盡管我們嘗試使用各種奇淫巧技來消除樣板代碼,可還是不太優(yōu)雅。

隨著近幾年MVVM的橫空出世,以及Android官方推出的全新架構(gòu)組件都在標(biāo)志著MVP已經(jīng)漸漸遠(yuǎn)離主流的項(xiàng)目搭建。

說到這里讓我不禁的想起世界杯解說中的一句話:

人生有多少個(gè)十年,可以陪伴一個(gè)人的所有高峰與低谷,可是當(dāng)我站立在人潮中,看千百雙手揮舞,卻再也看不到你的影蹤。

雖然我們需要更高效更完美的架構(gòu),但是更應(yīng)該把MVP帶給我們的架構(gòu)思想以及深處的精髓留在心中,將來無論遇到什么框架,對(duì)邏輯美的執(zhí)念會(huì)幫助我們走的更遠(yuǎn)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容