通用的Android客戶端架構(gòu)設(shè)計

客戶端架構(gòu)設(shè)計

客戶端設(shè)計 目的是整體設(shè)計客戶端App瘫里,架構(gòu)上打好鋪墊.

Android客戶端架構(gòu)設(shè)計

主要從以下幾個方面進(jìn)行設(shè)計:MVP設(shè)計風(fēng)格沐兵、整體架構(gòu)依沮、日志系統(tǒng)茧球、網(wǎng)絡(luò)系統(tǒng)庭瑰、本地存儲Test模塊.

MVP設(shè)計風(fēng)格

MVP即“Model —— Presenter —— View”抢埋,應(yīng)用在Android中可以實(shí)現(xiàn)Activity和業(yè)務(wù)邏輯的解耦弹灭,簡化Activity的規(guī)模【韭ⅲ現(xiàn)在Gitbub上暫時沒有合適的通用的MVP框架穷吮,我們可以基于Gitbub: Android MVP Demo 開源項(xiàng)目實(shí)現(xiàn)MVP模式。也可參考MVP開源項(xiàng)目Simple_news: MVP新聞客戶端饥努。

基本原理:

  • View:接口捡鱼,聲明所有的View相關(guān)的操作,包括GetValue酷愧、SetValue驾诈、Progress、Navigator等溶浴。MVP思想的核心乍迄,通過提取View接口,實(shí)現(xiàn)了Activity和Presenter的解耦戳葵。

  • Activity: View接口的實(shí)現(xiàn)就乓,初始化界面,初始化View中的控件拱烁,調(diào)用Presenter完成業(yè)務(wù)邏輯

  • Model:涉及到的數(shù)據(jù)對象,以及對數(shù)據(jù)的操作噩翠,比如可以把IO操作放到Model層

  • Presenter:業(yè)務(wù)邏輯的實(shí)現(xiàn)戏自,業(yè)務(wù)邏輯處理完成之后通過View接口操作UI,作用的數(shù)據(jù)是Model.

整體架構(gòu)

依賴注入型框架:

-- Dagger

阿里手淘項(xiàng)目推薦使用
項(xiàng)目地址:https://github.com/square/dagger
原理剖析文檔:http://square.github.io/dagger/

-- ButterKnife
視圖注入型框架
項(xiàng)目地址:https://github.com/JakeWharton/butterknife
文檔介紹:http://jakewharton.github.io/butterknife/

Butterknife的具體用法參考文檔說明伤锚,這里簡單介紹其特性擅笔。

  • 支持Activity的View注入,比如簡化Activity中的findViewById()
  • 支持View中的View注入屯援,比如簡化View.findViewById()
  • 支持View的事件回調(diào)

注入示例代碼如下,更多注入示例請參考文檔:

public class ExampleActivity extends Activity {
    @Bind(R.id.title) TextView title;
    @Bind(R.id.subtitle) TextView subtitle;
    @Bind(R.id.footer) TextView footer;

    @Override 
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.simple_activity);
      ButterKnife.bind(this);
      // TODO Use fields...
    }
    
    @OnClick(R.id.submit)
    public void submit(View view) {
      // TODO submit data to server...
    }
  
    @OnClick(R.id.submit)
    public void sayHi(Button button) {
       button.setText("Hello!");
    }
 }

日志系統(tǒng)

日志系統(tǒng)要完成以下幾個功能:

  • Debug時的日志需求

  • 日志寫入文件的需求猛们,方便上線查看

  • 日志上報

  • 日志加密

  • 系統(tǒng)日志監(jiān)控:日志奔潰信息監(jiān)控

修改醫(yī)行者中的日志系統(tǒng)可以達(dá)到需求, 也可以修改Github開源項(xiàng)目格式化日志輸出項(xiàng)目: Logger日志收集項(xiàng)目:Log 達(dá)到要求。

網(wǎng)絡(luò)系統(tǒng)

Gitbub: OkHttp

OkHttp封裝:HttpGet狞洋、HttpPost弯淘、File Upload,OKHttp的使用要求創(chuàng)建Request吉懊,填寫RequestBody庐橙。參照醫(yī)行者M(jìn)essaage的封裝形式假勿,將創(chuàng)建Request的過程進(jìn)行封裝,由最簡單的請求信息和回調(diào)接口構(gòu)成一個Message态鳖,并對Message進(jìn)行統(tǒng)一處理转培。

本地存儲

本地存儲要解決的問題:

  • 數(shù)據(jù)庫存儲

  • 數(shù)據(jù)庫的版本管理:版本升級、數(shù)據(jù)遷移等

參考:Hibernate的ORM思想

第三方框架:

-- GreenDAO

Android Sqlite orm 的 db 工具類

項(xiàng)目地址:https://github.com/greenrobot/greenDAO

文檔介紹:http://greendao-orm.com/documentation/

官網(wǎng)網(wǎng)址:http://greendao-orm.com/

GreenDao使用方式

  1. 創(chuàng)建 "Green Dao Generation Project" 來生成 entities and core classes( DaoMaster, DaoSession .etc);

  2. 在Android Project中使用生成的Dao浆竭,

GreenDao生成:

public class ExampleDaoGenerator {

    public static void main(String[] args) throws Exception {浸须、

        // 這兩個參數(shù)是:數(shù)據(jù)庫版本號和schema名稱

        Schema schema = new Schema(1000, "de.greenrobot.daoexample");

        addNote(schema);

        //addCustomerOrder(schema);

        // 生成類,同時可以指定java文件位置

        new DaoGenerator().generateAll(schema, "../DaoExample/src/main/java");

    }

    private static void addNote(Schema schema) {

        Entity note = schema.addEntity("Note");

        note.addIdProperty();

        note.addStringProperty("text").notNull();

        note.addStringProperty("comment");

        note.addDateProperty("date");

    }

}
  1. 針對版本升級的問題邦泄,GreenDao也有合適的解決方式:

數(shù)據(jù)庫版本升級問題:

/** WARNING: Drops all table on Upgrade! Use only during development. */

public static class DevOpenHelper extends OpenHelper {

    public DevOpenHelper(Context context, String name, CursorFactory factory) {

        super(context, name, factory);

}

@Override

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");

    //dropAllTables(db, true);

    //onCreate(db);

    // to do update database

}

Android Project和Java Generate整合可參考: 整合

以上是從官方文檔上大致看下來的結(jié)果羽戒,該開源項(xiàng)目在業(yè)界評價甚高,使用的人也不在少數(shù)虎韵。

Test模塊

Android單元測試

-- robolectric

項(xiàng)目地址:https://github.com/robolectric/robolectric

Demo 地址:https://github.com/robolectric/robolectricsample

文檔介紹:http://robolectric.org/

特點(diǎn):(1). 不需要模擬器在一般 JVM 就可以運(yùn)行測試用例(該框架在Java層實(shí)現(xiàn)了一套接口模擬Android易稠,所以可以直接在JVM上跑Android Unit Test)

(2). 能完成在真機(jī)上的大部分測試包括感應(yīng)器

其他的測試用例及相關(guān)模塊 Mock 可見:android-mock, mockito, easy-mock

robolectric

舉個例子:

Andorid中的代碼

public class MainActivity extends AppCompatActivity {

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        TextView textView =       (TextView)findViewById(R.id.textView1);

        textView.setOnClickListener(new OnClickListener() {

            @Override

            public void onClick(View v) {

                  startActivity(new Intent(MainActivity.this, SecondActivity.class));
            }

        });
    }
}

對應(yīng)的測試類,MainActivityTest的代碼:

@RunWith(RobolectricGradleTestRunner.class)

@Config(constants = BuildConfig.class, sdk = 21)

public class MainActivityTest {

    @Test

    public void testMainActivity() {

        MainActivity mainActivity = Robolectric.setupActivity(MainActivity.class);

        mainActivity.findViewById(R.id.textView1).performClick();

        Intent expectedIntent = new Intent(mainActivity, SecondActivity.class);

        ShadowActivity shadowActivity = Shadows.shadowOf(mainActivity);

        Intent actualIntent = shadowActivity.getNextStartedActivity();

        Assert.assertEquals(expectedIntent, actualIntent);

    }
}

使用方式

robolectric-demo

-- Monkey

Monkey是Android中的一個命令行工具包蓝,可以運(yùn)行在模擬器里或?qū)嶋H設(shè)備中驶社,基于adb shell命令還控制程序包進(jìn)行測試。它向系統(tǒng)發(fā)送偽隨機(jī)的用戶事件流(如按鍵輸入测萎、觸摸屏輸入亡电、手勢輸入等),實(shí)現(xiàn)對正在開發(fā)的應(yīng)用程序進(jìn)行壓力測試硅瞧。Monkey測試是一種為了測試軟件的穩(wěn)定性份乒、健壯性的快速有效的方法。Monkey測試對象是應(yīng)用程序包腕唧。

Monkey測試的步驟:
1或辖、#adb shell
2、#monkey -p com.android.calculator2 -v 500 (-p packageName -v LogLevel 500即偽隨機(jī)事件個數(shù))
更多地命令組合和參數(shù)可以查看:
Google Monkey官網(wǎng):http://developer.android.com/tools/help/monkey.html
Android-Monkey-Test:http://ihongqiqu.com/2015/12/24/Android-Monkey-Test/

第三方測試工具

-- Tencent APT

APT 是騰訊開源的一個 Android 平臺高效性能測試組件枣接,提供豐富實(shí)用的功能颂暇,適用于開發(fā)自測、定位性能瓶頸但惶;測試人員完成性能基準(zhǔn)測試耳鸯、競品對比測試

項(xiàng)目地址:https://github.com/stormzhang/APT

以上作為參考,后續(xù)還將繼續(xù)完善膀曾。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末县爬,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子添谊,更是在濱河造成了極大的恐慌财喳,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件碉钠,死亡現(xiàn)場離奇詭異纲缓,居然都是意外死亡卷拘,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門祝高,熙熙樓的掌柜王于貴愁眉苦臉地迎上來栗弟,“玉大人,你說我怎么就攤上這事工闺≌Ш眨” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵陆蟆,是天一觀的道長雷厂。 經(jīng)常有香客問我,道長叠殷,這世上最難降的妖魔是什么改鲫? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮林束,結(jié)果婚禮上像棘,老公的妹妹穿的比我還像新娘。我一直安慰自己壶冒,他們只是感情好缕题,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著胖腾,像睡著了一般烟零。 火紅的嫁衣襯著肌膚如雪咸作。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天性宏,我揣著相機(jī)與錄音,去河邊找鬼毫胜。 笑死诬辈,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的焙糟。 我是一名探鬼主播口渔,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼缺脉,長吁一口氣:“原來是場噩夢啊……” “哼痪欲!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起攻礼,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤业踢,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后礁扮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體知举,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年太伊,在試婚紗的時候發(fā)現(xiàn)自己被綠了雇锡。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡僚焦,死狀恐怖锰提,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情芳悲,我是刑警寧澤立肘,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站芭概,受9級特大地震影響赛不,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜罢洲,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一踢故、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧惹苗,春花似錦殿较、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至院究,卻和暖如春洽瞬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背业汰。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工伙窃, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人样漆。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓为障,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子鳍怨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,077評論 25 707
  • afinalAfinal是一個android的ioc呻右,orm框架 https://github.com/yangf...
    passiontim閱讀 15,429評論 2 45
  • 早就知道Terrible 2 Horrible 3(可怕的2歲,恐怖的3歲)的說法鞋喇,航航現(xiàn)在2歲半声滥,確實(shí)呈現(xiàn)了一些...
    大J小M成長記閱讀 1,466評論 0 4
  • 我們都承諾過 遇見美好的事物 就要想起對方 然后我在漆黑的夜晚發(fā)呆 也想起你了 不知道遇見了什么。
    留子堯閱讀 232評論 0 10