關(guān)于地址選擇器的思考與實(shí)踐

前言

我們知道,地址選擇器是一個(gè)通用組件密幔,網(wǎng)上的開(kāi)源項(xiàng)目也有很多楔脯。那么為什么還會(huì)有這篇文章呢?因?yàn)槲以谡{(diào)研過(guò)程中發(fā)現(xiàn)老玛,雖然都是地址選擇器淤年,但是實(shí)現(xiàn)的方式卻各不相同。以下是調(diào)研地址選擇器的一些總結(jié)和思考實(shí)踐蜡豹。希望對(duì)大家有幫助麸粮,大家有什么更好的想法,也要告知我哦~

地址選擇器實(shí)現(xiàn)方式介紹

  • 本地存放area.db文件
    大多數(shù)App都是此種實(shí)現(xiàn)

    • 優(yōu)點(diǎn):?jiǎn)?dòng)快镜廉,不受網(wǎng)絡(luò)影響
    • 缺點(diǎn):
      • 不能實(shí)時(shí)更新弄诲,數(shù)據(jù)更新依賴發(fā)布新版本。(或則自己實(shí)現(xiàn)一套更新機(jī)制娇唯,文件從后端下載齐遵,實(shí)現(xiàn)較為復(fù)雜)
      • 各端(服務(wù)器、前端塔插、移動(dòng)端)需要維護(hù)一份相同的地址信息表梗摇,維護(hù)成本高。
      • 地址信息表本地保存想许,增大安裝包體積
  • 一次性從服務(wù)端拉取所有地址信息
    在App啟動(dòng)時(shí)候伶授,一次性拉取所有地址信息。

    • 優(yōu)點(diǎn):數(shù)據(jù)可配置流纹、請(qǐng)求少
    • 缺點(diǎn):
      • 每次啟動(dòng)都請(qǐng)求服務(wù)器糜烹,大部分是無(wú)用請(qǐng)求,浪費(fèi)了服務(wù)器資源漱凝。
      • 請(qǐng)求數(shù)據(jù)量大
    • 優(yōu)化方案:更換請(qǐng)求時(shí)機(jī)疮蹦,點(diǎn)擊選擇地址的時(shí)候才去一次性請(qǐng)求所有數(shù)據(jù)。但是還是不能避免請(qǐng)求數(shù)據(jù)量過(guò)大問(wèn)題茸炒。
  • 實(shí)時(shí)獲取省愕乎、市阵苇、區(qū)信息,選中上一級(jí)才去獲取對(duì)應(yīng)的下一級(jí)數(shù)據(jù)
    如:京東

    • 優(yōu)點(diǎn):數(shù)據(jù)可配置妆毕,請(qǐng)求數(shù)據(jù)量小
    • 缺點(diǎn):請(qǐng)求較多慎玖,需要處理的異常case較多
    • 思考優(yōu)化方案:每次喚起地址選擇器時(shí),緩存獲取的地址信息歷史數(shù)據(jù)笛粘。顯示地址信息的時(shí)候趁怔,只有本地緩存沒(méi)有當(dāng)前數(shù)據(jù),才向服務(wù)端發(fā)送請(qǐng)求薪前。(其實(shí)這種場(chǎng)景很少出現(xiàn)润努,但是再小的蒼蠅也是肉,能優(yōu)化就優(yōu)化了吧……)

因?yàn)橛脩艋臼窃谟芯W(wǎng)絡(luò)的情況下才會(huì)使用示括,所以選擇聯(lián)網(wǎng)獲取地址信息也是合理的铺浇。又考慮到網(wǎng)絡(luò)請(qǐng)求的大小,服務(wù)端性能影響垛膝,安裝包大小以及地址信息可配置性等因素鳍侣,實(shí)時(shí)獲取地址信息是一個(gè)不錯(cuò)的方式。下面介紹地址選擇器實(shí)現(xiàn)一些關(guān)鍵點(diǎn)吼拥。

實(shí)時(shí)獲取信息的地址選擇器設(shè)計(jì)

先來(lái)看效果倚聚,如下圖所示。喚起地址選擇器會(huì)有一次省份的網(wǎng)絡(luò)請(qǐng)求凿可,之后每一級(jí)數(shù)據(jù)都是實(shí)時(shí)去獲取惑折。在當(dāng)前地址選擇器喚起狀態(tài),獲取之后就將歷史數(shù)據(jù)保存在本地枯跑,下一次就不再發(fā)送網(wǎng)絡(luò)請(qǐng)求了惨驶。


地址選擇器效果圖
地址選擇器效果圖

數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)

當(dāng)前的地址信息按照省、市敛助、區(qū)/縣粗卜、街道四級(jí)劃分,后一級(jí)總是和前一級(jí)相關(guān)聯(lián)纳击。

  • Province
public class Province {
    public long id;
    public String name;
}
  • City
public class City  {
    public long id;
    public long province_id;
    public String name;
}
  • County
public class County {
    public long id;
    public long city_id;
    public String name;
}
  • Street
public class Street {
    public long id;
    public long county_id;
    public String name;
}

回調(diào)接口設(shè)計(jì)

主要提供了4個(gè)回調(diào)方法:

public interface OnAddressSelectedListener {
    // 獲取地址完成回調(diào)
    void onAddressSelected(Province province, City city, County county, Street street);
    // 選取省份完成回調(diào)
    void onProvinceSelected(Province province);
    // 選取城市完成回調(diào)
    void onCitySelected(City city);
    // 選取區(qū)/縣完成回調(diào)
    void onCountySelected(County county);
}

這里著重說(shuō)一下onAddressSelected回調(diào)方法续扔,其是在地址選擇完成的時(shí)候調(diào)用。那么是如何判斷地址選擇已經(jīng)完成呢评疗。這個(gè)在AddressSelector中有如下一個(gè)機(jī)制测砂。
每次一個(gè)級(jí)別選擇完成后茵烈,會(huì)獲取下一個(gè)級(jí)別的數(shù)據(jù)(網(wǎng)絡(luò)請(qǐng)求或者緩存獲劝俅摇)進(jìn)行顯示。顯示的時(shí)候有這么一個(gè)邏輯呜投,當(dāng)前級(jí)別有數(shù)據(jù)加匈,則正常顯示存璃;若沒(méi)有,則說(shuō)明地址選擇已經(jīng)完成雕拼,此時(shí)調(diào)用onAddressSelected方法纵东。

緩存設(shè)計(jì)

我們這里默認(rèn)服務(wù)端每個(gè)地址的id都是唯一的。緩存機(jī)制比較簡(jiǎn)單啥寇,可以看下如下的流程圖偎球。

緩存機(jī)制流程圖
緩存機(jī)制流程圖

  1. 建立三個(gè)緩存map,分別緩存始稹-市衰絮、市-區(qū)區(qū)-街道
/** 緩存數(shù)據(jù):省-市 */
private ArrayMap<Long, List<City>> province2city = new ArrayMap<>();
/** 緩存數(shù)據(jù):市-區(qū) */
private ArrayMap<Long, List<County>> city2county = new ArrayMap<>();
/** 緩存數(shù)據(jù):區(qū)-街道 */
private ArrayMap<Long, List<Street>> county2street = new ArrayMap<>();
  1. 選擇省磷醋、市猫牡、區(qū)某一級(jí)時(shí),先查看是否有緩存數(shù)據(jù)邓线,若有則使用緩存數(shù)據(jù)淌友;若沒(méi)有,則向服務(wù)端發(fā)送網(wǎng)絡(luò)請(qǐng)求骇陈。
// 有緩存則直接使用緩存,否則去重新請(qǐng)求
if(province2city.containsKey(province.id)){
    setCities(province2city.get(province.id));
} else {
    progressBar.setVisibility(View.VISIBLE);
    listener.onProvinceSelected(province);
}

3震庭、每次獲取的歷史數(shù)據(jù),存儲(chǔ)在相應(yīng)的緩存map中缩歪。

province2city.put(provinceId, cities);

控件使用

  1. gradle導(dǎo)入控件
compile 'com.zr.addressselector:library:1.0.1'
  1. Activity實(shí)現(xiàn)OnAddressSelectedListener接口
public class MainActivity extends AppCompatActivity implements OnAddressSelectedListener
  1. 展現(xiàn)地址選擇器
dialog = new BottomSelectorDialog(MainActivity.this);
dialog.setOnAddressSelectedListener(MainActivity.this);
dialog.show();
  1. 根據(jù)網(wǎng)絡(luò)返回归薛,設(shè)置數(shù)據(jù)
dialog.getSelector().setProvinces(Collections.singletonList(province));
  1. 控件提供的幾個(gè)設(shè)置方法
/**
     * 設(shè)置回調(diào)接口
     * @param listener
     */
    public void setOnAddressSelectedListener(OnAddressSelectedListener listener) {
        this.listener = listener;
    }

    /**
     * 設(shè)置省列表
     * @param provinces 省份列表
     */
    public void setProvinces(List<Province> provinces){
        handler.sendMessage(Message.obtain(handler, WHAT_PROVINCES_PROVIDED, provinces));
    }

    /**
     * 設(shè)置市列表
     * @param cities 城市列表
     */
    public void setCities(List<City> cities){
        handler.sendMessage(Message.obtain(handler, WHAT_CITIES_PROVIDED, cities));
    }

    /**
     * 設(shè)置區(qū)列表
     * @param countries 區(qū)/縣列表
     */
    public void setCountries(List<County> countries){
        handler.sendMessage(Message.obtain(handler, WHAT_COUNTIES_PROVIDED, countries));
    }

    /**
     * 設(shè)置街道列表
     * @param streets 街道列表
     */
    public void setStreets(List<Street> streets){
        handler.sendMessage(Message.obtain(handler, WHAT_STREETS_PROVIDED, streets));
    }

寫(xiě)在最后

雖然提供了gradle compile導(dǎo)入的方式,但是整個(gè)控件的源碼其實(shí)是很簡(jiǎn)單的匪蝙。如果有定制需求主籍,可以到這里下載源碼。

項(xiàng)目源碼下載:ZRAddressSelector

特別感謝

JDAddressSelector逛球,本組件設(shè)計(jì)也是受此開(kāi)源項(xiàng)目啟發(fā)千元,非常感謝作者開(kāi)源~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市颤绕,隨后出現(xiàn)的幾起案子幸海,更是在濱河造成了極大的恐慌,老刑警劉巖奥务,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件物独,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡氯葬,警方通過(guò)查閱死者的電腦和手機(jī)挡篓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人官研,你說(shuō)我怎么就攤上這事秽澳。” “怎么了戏羽?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵担神,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我始花,道長(zhǎng)妄讯,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任酷宵,我火速辦了婚禮捞挥,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘忧吟。我一直安慰自己砌函,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布溜族。 她就那樣靜靜地躺著讹俊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪煌抒。 梳的紋絲不亂的頭發(fā)上仍劈,一...
    開(kāi)封第一講書(shū)人閱讀 49,816評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音寡壮,去河邊找鬼贩疙。 笑死,一個(gè)胖子當(dāng)著我的面吹牛况既,可吹牛的內(nèi)容都是我干的这溅。 我是一名探鬼主播,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼棒仍,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼悲靴!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起莫其,我...
    開(kāi)封第一講書(shū)人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤癞尚,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后乱陡,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體浇揩,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年憨颠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了胳徽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖膜廊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情淫茵,我是刑警寧澤爪瓜,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站匙瘪,受9級(jí)特大地震影響铆铆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜丹喻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一薄货、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧碍论,春花似錦谅猾、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至藏研,卻和暖如春敬矩,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蠢挡。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工弧岳, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人业踏。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓禽炬,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親勤家。 傳聞我的和親對(duì)象是個(gè)殘疾皇子瞎抛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

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

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)却紧,斷路器桐臊,智...
    卡卡羅2017閱讀 134,633評(píng)論 18 139
  • 國(guó)家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說(shuō)閱讀 10,928評(píng)論 6 13
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法晓殊,內(nèi)部類的語(yǔ)法断凶,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法巫俺,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,598評(píng)論 18 399
  • API定義規(guī)范 本規(guī)范設(shè)計(jì)基于如下使用場(chǎng)景: 請(qǐng)求頻率不是非常高:如果產(chǎn)品的使用周期內(nèi)請(qǐng)求頻率非常高认烁,建議使用雙通...
    有涯逐無(wú)涯閱讀 2,521評(píng)論 0 6
  • 寫(xiě)在90這天 今天終于用郵箱注冊(cè)了賬號(hào),然后報(bào)名了,其實(shí)心里有點(diǎn)慌却嗡,有時(shí)候覺(jué)得自己復(fù)習(xí)了這么久完全沒(méi)進(jìn)步舶沛,很疲憊,...
    cheon閱讀 157評(píng)論 0 0