Android MVP升級路(三)爲所欲爲的旗艦版

01 序

  1. 第1、二章中有些類的命名存在筆誤,目前發現的已糾正。bash

  2. 若是你有把前兩篇文章認真的看完,那麼你已經基本掌握了MVP架構核心思想,能夠在實際開發項目中使用它了。架構

  3. 有很多問我要源碼demo的朋友,demo確實有,前面文章之因此沒留下源碼是由於我更但願你可以親手寫出來一套屬於本身的東西,在這過程當中你能夠反覆斟酌各層之間的邏輯,包結構以及如何設計父類的通用方法。建議還沒手寫過的朋友停下來去寫一套本身的MVP。框架

  4. 鑑於前面文章已經算是MVP的入門,本文主要聊一些實際使用中架構項目時的思考。ide

02 Token的有效性

在第二章中咱們利用了相似策略模式的方法對Model層實現了統一管理,利用Token標識不一樣的model,但是這樣會存在一些隱患。優化

例如當咱們給一個已經登記在Token中的Model類改了名字,必須同時去Token中更新手動一下對應的字符串。拋開增長維護成本不說,一旦有一個類咱們忘記手動更新,那麼它就不能用了。ui

顯然,意識到這個問題後此方法必須馬上優化。spa

放棄Token,直接對類反射設計

上一章說道,token其實就是描述某個model類「包名+類名」的字符串,有了它咱們就能夠獲得這個類對應的class對象,從而實例化出對象: model = (BaseModel)Class.forName(token).newInstance(); // 使用token實例化對象code

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

public class DataModel {
        public static BaseModel request(Class clazz) {
            // 聲明一個空的BaseModel
            BaseModel model = null;
            // 判斷class對象是否是BaseModel的實例
            if (clazz instanceof BaseModel) {
                try {
                    //利用反射機制得到對應Model對象的引用
                    model = (BaseModel) clazz.newInstance();
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
            return model;
        }
    }
複製代碼

請求數據時直接傳遞model的class對象便可:

DataModel
                // 設置Model
                .request(UserDataModel.class)
                // 添加請求參數,沒有則不添加
                .params(userId)
                // 註冊監聽回調
                .execute(new UserCallback());
複製代碼

到此咱們已經解決了token方法中更新類名須要手動同步的問題,可是還並不完美。假如一個項目中有10處位置調用了同一個model,當這個model類名有變化時這10處均發生了改變,雖然IDE會自動幫咱們修改其餘地方,可是終究仍是發生了多餘的變化。

理想狀態下,咱們但願不管model被多少處調用,它自身的改變並不會影響其餘地方,那要怎麼作呢?方法有不少,好比採用Token<Key,Value>方法映射等等,你們一塊兒想一想呀歡迎留言~

03 通用的callback

在數據請求中咱們須要在callback的各個回調中分別取處理對應的請求結果,可是你只要寫多了就會發現,除了請求成功的回調方法,其餘的像請求失敗,請求出錯這些方法咱們作的事幾乎是同樣的。

那既然這樣,咱們是否是能夠構建一個通用的BaseCallback去處理請求的異常狀況呢?

04 連接view

在第一章咱們封裝了base層後,雖然大大的減小冗餘代碼,可是在每一個activity咱們都要去手動操做presenter與view的連接與斷開操做,這顯然不是很美好的。

優化的辦法也很簡單,咱們都知道每一個activity都繼承於BaseActivity,每一個presenter都繼承於BasePresenter,因此,咱們只須要在BaseActivity中實現BasePresenter連接view的操做便可。

在BaseActivity中:

public abstract class BaseActivity extends Activity implements BaseView {

    /**
     * 獲取Presenter實例,子類實現
     */
    public abstract BasePresenter getPresenter();

    /**
     * 初始化Presenter的實例,子類實現
     */
    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();
    }

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

在上面的例子中,我爲了更直觀的展現效果設計了兩個抽象方法,分別是初始化和獲取presenter,固然其實徹底能夠只有一個獲取presenter方法就行,看本身喜愛便可。

05 思想

能讀到這裏的朋友相信都是真愛沒錯了,不知道朋友你有沒有發現不管是前兩章講的那麼詳細可是沒給源碼,仍是這章的點到爲止,我都是在強調思想要遠比代碼重要。

其實MVP自己的代碼,格式什麼的並是不那麼重要,重要的它的核心思想,以一種什麼樣的方式工做的。當你徹底理解了它的思想,你就能夠按照本身的喜愛隨意優化架構。

06 無奈的沒落

回想起大學那會剛接觸MVP時真的被驚豔到了,不一樣類別的邏輯代碼被劃分的層次分明,但是隨着時間的慢慢推移,MVP的缺陷也愈來愈明顯,那就是代碼太過冗餘,儘管咱們嘗試使用各類奇淫巧技來消除樣板代碼,可仍是不太優雅。

隨着近幾年MVVM的橫空出世,以及Android官方推出的全新架構組件都在標誌着MVP已經漸漸遠離主流的項目搭建。

說到這裏讓我不由的想起世界盃解說中的一句話:

人生有多少個十年,能夠陪伴一我的的全部高峯與低谷,但是當我站立在人潮中,看千百雙手揮舞,卻再也看不到你的影蹤。

雖然咱們須要更高效更完美的架構,可是更應該把MVP帶給咱們的架構思想以及深處的精髓留在心中,未來不管遇到什麼框架,對邏輯美的執念會幫助咱們走的更遠。

相關文章
相關標籤/搜索