WMRouter:美團外賣Android開源路由框架
WMRouter是一款Android路由框架,基於元件化的設計思路,功能靈活,使用也比較簡單。
WMRouter最初用於解決美團外賣C端App在業務演進過程中的實際問題,之後逐步推廣到了美團其他App,因此我們決定將其開源,希望更多技術同行一起開發,應用到更廣泛的場景裡去。Github專案地址與使用文件詳見 https://github.com/meituan/WMRouter。
本文先簡單介紹WMRouter的功能和適用場景,然後詳細介紹WMRouter的發展背景和過程。
功能簡介
WMRouter主要提供URI分發、ServiceLoader兩大功能。
URI分發功能可用於多工程之間的頁面跳轉、動態下發URI連結的跳轉等場景,特點如下:
- 支援多scheme、host、path
- 支援URI正則匹配
- 頁面配置支援Java程式碼動態註冊,或註解配置自動註冊
- 支援配置全域性和區域性攔截器,可在跳轉前執行同步/非同步操作,例如定位、登入等
- 支援單次跳轉特殊操作:Intent設定Extra/Flags、設定跳轉動畫、自定義StartActivity操作等
- 支援頁面Exported控制,特定頁面不允許外部跳轉
- 支援配置全域性和區域性降級策略
- 支援配置單次和全域性跳轉監聽
- 完全元件化設計,核心元件均可擴充套件、按需組合,實現靈活強大的功能
基於SPI (Service Provider Interfaces) 的設計思想,WMRouter提供了ServiceLoader模組,類似Java中的java.util.ServiceLoader
- 使用註解自動配置
- 支援獲取介面的所有實現,或根據Key獲取特定實現
- 支援獲取Class或獲取例項
- 支援無參構造、Context構造,或自定義Factory、Provider構造
- 支援單例管理
- 支援方法呼叫
其他特性:
- 優化的Gradle外掛,對編譯耗時影響很小
- 編譯期和執行時配置檢查,避免配置衝突和錯誤
- 編譯期自動新增Proguard混淆規則,免去手動配置的繁瑣
- 完善的除錯功能,幫助及時發現問題
適用場景
WMRouter適用但不限於以下場景:
-
Native+H5混合開發模式,需要進行頁面之間的互相跳轉,或進行靈活的運營跳轉連結下發。可以利用WMRouter統一頁面跳轉邏輯,根據不同的協議(HTTP、HTTPS、用於Native頁面的自定義協議)跳轉對應頁面,且在跳轉過程中可以使用UriInterceptor對跳轉連結進行修改,例如跳轉H5頁面時在URL中加引數。
-
統一管理來自App外部的URI跳轉。來自App外部的URI跳轉,如果使用Android原生的Manifest配置,會直接啟動匹配的Activity,而很多時候希望先正常啟動App開啟首頁,完成常規初始化流程(例如登入、定位等)後再跳轉目標頁面。此時可以使用統一的Activity接收所有外部URI跳轉,到首頁時再用WMRouter啟動目標頁面。
-
頁面跳轉有複雜判斷邏輯的場景。例如多個頁面都需要先登入、先定位後才允許開啟,如果使用常規方案,這些頁面都需要處理相同的業務邏輯;而利用WMRouter,只需要開發好UriInterceptor並配置到各個頁面即可。
-
多工程、元件化、平臺化開發。多工程開發要求各個工程之間能互相通訊,也可能遇到和外賣App類似的程式碼複用、依賴注入、編譯等問題,這些問題都可以利用WMRouter的URI分發和ServiceLoader模組解決。
-
對業務埋點需求較強的場景。頁面跳轉作為最常見的業務邏輯之一,常常需要埋點。給每個頁面配置好URI,使用WMRouter統一進行頁面跳轉,並在全域性的OnCompleteListener中埋點即可。
-
對App可用性要求較高的場景。一方面,可以對頁面跳轉失敗進行埋點監控上報,及時發現線上問題;另一方面,頁面跳轉時可以執行判斷邏輯,發現異常(例如服務端異常、客戶端崩潰等)則自動開啟降級後的頁面,保證關鍵功能的正常工作,或給使用者友好的提示。
-
頁面A/B測試、動態配置等場景。在WMRouter提供的介面基礎上進行少量開發配置,就可以實現:根據下發的A/B測試策略跳轉不同的頁面實現;根據不同的需要動態下發一組路由表,相同的URI跳轉到不同的一組頁面(實現方面可以自定義UriInterceptor,對匹配的URI返回301的UriResult使跳轉重定向)。
基本概念解釋
下面開始介紹WMRouter的發展背景和過程。為了方便後文的理解,我們先簡單瞭解和回顧幾個基本概念。
路由
根據維基百科的解釋,路由(routing)可以理解成在互聯的網路通過特定的協議把資訊從源地址傳輸到目的地址的過程。一個典型的例子就是在網際網路中,路由器可以根據IP協議將資料傳送到特定的計算機。
URI
URI(Uniform Resource Identifier,統一資源識別符號)是一個用於標識某一網際網路資源名稱的字串。URI的組成如下圖所示。
一些常見的URI舉例如下,包括平時經常用到的網址、IP地址、FTP地址、檔案、打電話、發郵件的協議等。
- ftp://example.org/resource.txt
- file:///Users/
- tel:863-1234
- mailto:[email protected]
在Android中也提供了android.net.Uri
工具類用於處理URI,Android中URI常用的幾個部分主要是scheme、host、path和query。
Android中的Intent跳轉
在Android中的Intent跳轉,分為顯式跳轉和隱式跳轉兩種。
顯式跳轉即指定ComponentName(類名)的Intent跳轉,一般通過Bundle傳參,示例程式碼如下:
Intent intent = new Intent(context, TestActivity.class);
intent.putExtra("param", "value")
startActivity(intent);
隱式跳轉即不指定ComponentName的Intent跳轉,通過IntentFilter找到匹配的元件,IntentFilter支援action、category和data的匹配,其中data就是URI。例如下面的程式碼,會啟動系統預設的瀏覽器開啟網頁:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.meituan.com"))
startActivity(intent);
Activity通過Manifest配置IntentFilter,例如下面的配置可以匹配所有形如demo_scheme://demo_host/***
的URI。
<activity android:name=".app.UriProxyActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="demo_scheme" android:host="demo_host"/>
</intent-filter>
</activity>
URI跳轉
在美團外賣C端早期開發過程中,產品希望通過後臺下發URI控制客戶端跳轉指定頁面,從而實現靈活的運營配置。外賣App採用了Native+H5的混合開發模式,Native頁面定義了專用的URI,而H5頁面則使用HTTP/HTTPS連結在專門的WebView容器中載入,兩種連結的跳轉邏輯不同,實現起來比較繁瑣。
Native頁面的URI跳轉最開始使用的是Android原生的IntentFilter,通過隱式跳轉啟動,但是這種方式存在靈活性差、功能缺失、Bug多等問題。例如:
-
從外部(瀏覽器、微信等)跳轉外賣的URI時,系統會直接開啟相應的Activity,而沒有經過歡迎頁的正常啟動流程,一些程式碼邏輯可能沒有執行,例如定位邏輯。
-
有很多頁面在開啟前需要確保使用者先登入或先定位,每個頁面都寫一遍判斷登入、定位的邏輯非常麻煩,提高了開發維護成本。
-
運營人員可能會配錯URI,頁面跳轉失敗,有些跳轉的地方沒有做try-catch處理,會產生Crash;有些地方雖然加了try-catch,但跳轉失敗後沒有任何響應,使用者體驗差;跳轉失敗沒有監控,不能及時發現和解決線上業務異常。
為了解決上述問題,我們希望有一個Android的URI分發元件,可以根據URI中不同的scheme、host、path,進行不同的處理,同時能夠在頁面跳轉過程中進行更靈活的干預。調研發現,現有的一些Android路由元件主要都是在解決多工程之間解耦的問題,而URI往往只支援通過path分發,頁面跳轉的配置也不夠靈活,難以滿足實際需要。於是我們決定自行設計實現。
核心設計思路
下圖展示了WMRouter中URI分發機制的核心設計思路。借鑑網路請求的機制,WMRouter中的每次URI跳轉視為發起一個UriRequest;URI跳轉請求被WMRouter逐層分發給一系列的UriHandler進行處理;每個UriHandler處理之前可以被UriInterceptor攔截,並插入一些特殊操作。
頁面跳轉來源
常見的頁面跳轉來源如下:
- 來自App內部Native頁面的跳轉
- 來自App內Web容器的跳轉,即H5頁面發起的跳轉
- 從App外通過URI喚起App的跳轉,例如來自瀏覽器、微信等
- 從通知中心Push喚起App的跳轉
對於來自App內部和Web容器的跳轉,我們把所有跳轉程式碼統一改成呼叫WMRouter處理,而來自外部和Push通知的跳轉則全部使用一個獨立的中轉Activity接收,再呼叫WMRouter處理。
UriRequest
UriRequest中包含Context、URI和Fields,其中Fields為HashMap,可以通過Key存放任意資料。簡單起見,UriRequest類同時承擔了Response的功能,跳轉請求的結果,也會被儲存到Fields中。Fields可以根據需要自定義,其中一些常見欄位舉例如下:
- Intent的Extra引數,Bundle型別
- 用於startActivityForResult的RequestCode,int型別
- 用於overridePendingTransition方法的頁面切換動畫資源,int[]型別
- 本次跳轉結果的監聽器,OnCompleteListener型別
每次URI跳轉請求會有一個ResultCode(類似HTTP請求的ResponseCode),表示跳轉結果,也存放在Fields中。常見Code如下,使用者也可以自定義Code:
- 200:跳轉成功
- 301:重定向到其他URI,會再次跳轉
- 400:請求錯誤,通常是Context或URI為空
- 403:禁止跳轉,例如跳轉白名單以外的HTTP連結、Activity的exported為false等
- 404:找不到目標(Activity或UriHandler)
- 500:發生錯誤
總結來說,UriRequest用於實現一次URI跳轉中所有元件之間的通訊功能。
UriHandler
UriHandler用於處理URI跳轉請求,可以巢狀從而逐層分發和處理請求。UriHandler是非同步結構,接收到UriRequest後處理(例如跳轉Activity等),如果處理完成,則呼叫callback.onComplete()
並傳入ResultCode;如果沒有處理,則呼叫callback.onNext()
繼續分發。下面的示例程式碼展示了一個只處理HTTP連結的UriHandler的實現:
public interface UriCallback {
/**
* 處理完成,繼續後續流程。
*/
void onNext();
/**
* 處理完成,終止分發流程。
*
* @param resultCode 結果
*/
void onComplete(int resultCode);
}
public class DemoUriHandler extends UriHandler {
public void handle(@NonNull final UriRequest request, @NonNull final UriCallback callback) {
Uri uri = request.getUri();
// 處理HTTP連結
if ("http".equalsIgnoreCase(uri.getScheme())) {
try {
// 呼叫系統瀏覽器
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(uri);
request.getContext().startActivity(intent);
// 跳轉成功
callback.onComplete(UriResult.CODE_SUCCESS);
} catch (Exception e) {
// 跳轉失敗
callback.onComplete(UriResult.CODE_ERROR);
}
} else {
// 非HTTP連結不處理,繼續分發
callback.onNext();
}
}
// ...
}
UriInterceptor
UriInterceptor為攔截器,不做最終的URI跳轉操作,但可以在最終的跳轉前進行各種同步/非同步操作,常見操作舉例如下:
- URI跳轉攔截,禁止特定的URI跳轉,直接返回403(例如禁止跳轉非meituan域名的HTTP連結)
- URI引數修改(例如在HTTP連結末尾新增query引數)
- 各種中間處理(例如開啟登入頁登入、獲取定位、髮網絡請求)
- ……
每個UriHandler都可以新增若干UriInterceptor。在UriHandler基類中,handle()方法先呼叫抽象方法shouldHandle()
判斷是否要處理UriRequest,如果需要處理,則逐個執行Interceptor,最後再呼叫handleInternal()
方法進行跳轉操作。
public abstract class UriHandler {
// ChainedInterceptor將多個UriInterceptor合併成一個
protected ChainedInterceptor mInterceptor;
public UriHandler addInterceptor(@NonNull UriInterceptor interceptor) {
if (interceptor != null) {
if (mInterceptor == null) {
mInterceptor = new ChainedInterceptor();
}
mInterceptor.addInterceptor(interceptor);
}
return this;
}
public void handle(@NonNull final UriRequest request, @NonNull final UriCallback callback) {
if (shouldHandle(request)) {
if (mInterceptor != null) {
mInterceptor.intercept(request, new UriCallback() {
@Override
public void onNext() {
handleInternal(request, callback);
}
@Override
public void onComplete(int result) {
callback.onComplete(result);
}
});
} else {
handleInternal(request, callback);
}
} else {
callback.onNext();
}
}
/**
* 是否要處理給定的uri。在Interceptor之前呼叫。
*/
protected abstract boolean shouldHandle(@NonNull UriRequest request);
/**
* 處理uri。在Interceptor之後呼叫。
*/
protected abstract void handleInternal(@NonNull UriRequest request, @NonNull UriCallback callback);
}
URI的分發與降級
在外賣C端App中的URI分發示意如下圖。所有URI跳轉都會分發到RootUriHandler,然後根據不同的scheme分發到不同的子Handler。例如waimai協議分發到WmUriHandler,然後進一步根據不同的path分發到子Handler,從而啟動相應的Activity;HTTP/HTTPS協議分發到HttpHandler,啟動WebView容器;對於其他型別URI(tel、mailto等),前面的幾個Handler都無法處理,則會分發到StartUriHandler,嘗試使用Android原生的隱式跳轉啟動系統應用。
每個UriHandler都可以根據實際需要實現降級策略,也可以不作處理繼續分發給其他UriHandler。RootUriHandler中提供了一個全域性的分發完成事件監聽器,當UriHandler處理失敗返回異常ResultCode或所有子UriHandler都沒有處理時,執行全域性降級策略。
平臺化與兩端複用
隨著外賣C端業務的演進,團隊成員擴充了數倍,商超生鮮等垂直品類的拆分,以及異地研發團隊的建立,客戶端的平臺化被提上日程。關於外賣平臺化更詳細的內容,可參考團隊之前已經發布的文章 美團外賣Android平臺化架構演進實踐。
為了滿足實際開發需要,在長時間的探索後,逐步形成了如圖所示的三層工程結構。
原有的單個工程拆分成多個工程,就不可避免的涉及到多工程之間的耦合問題,主要包括通訊問題、複用問題、依賴注入、編譯問題,下面詳細介紹。
通訊問題
當原先的一個工程拆分到各個業務庫後,業務庫之間的頁面需要進行通訊,最主要的場景就是頁面跳轉並通過Intent傳遞引數。
原先的頁面跳轉使用顯式跳轉,Activity之間存在強引用,當Activity被拆分到不同的業務庫,業務庫不能直接互相依賴,因此需要進行解耦。
利用WMRouter的URI分發機制,剛好可以很容易的解決這個問題。將將所有業務庫的Activity註冊到WMRouter,各個業務庫之間就可以進行頁面跳轉了。
此時WMRouter已經承載了兩項功能:
- 後臺下發的運營URI跳轉 (
waimai://*
) - 內部頁面跳轉,用於代替原有的顯式跳轉,實現工程解耦 (
wm_router://page/*
)
由於後臺下發的URI是和產品、運營、H5、iOS等各端統一制定的協議,支援的頁面、格式、引數等都不能隨意改動,而內部頁面跳轉使用的URI,則需要根據實際開發需要進行配置,兩套URI協議不能相容,因此使用了不同的scheme。
複用問題與ServiceLoader模組
業務庫之間經常需要複用程式碼。一些通用程式碼邏輯可以下沉到平臺層從而複用,例如業務無關的通用View元件;而有些程式碼不適合下沉到平臺層,例如業務庫A要使用業務庫B中的某個介面模組,而這個介面模組和業務庫B的耦合很緊密。具體到外賣實際業務場景中,商家頁在商家休息時會展示推薦商家列表,其樣式和首頁相同(如圖),而兩個頁面不在一個工程中,商家頁希望能直接從首頁業務庫中獲取商家列表的實現。
為了解決上述問題,我們調研瞭解到Java中SPI (Service Provider Interfaces) 的設計思想與java.util.ServiceLoader
工具類,還學習到美團平臺為了解決類似問題而開發的ServiceLoader元件。
考慮到實際需求差異,我們重新開發了自己的ServiceLoader實現。相比Java中的實現,WMRouter的實現借鑑了美團平臺的設計思路,不僅支援通過介面獲取所有實現類,還支援通過介面和唯一的Key獲取特定的實現類。另外WMRouter的實現還支援直接載入實現類的Class、用Factory和Provider建立物件、單例管理、方法呼叫等功能。在Gradle外掛的實現思路上,借鑑了美團平臺的ServiceLoader並做了效能優化,給平臺提出了改進建議。
業務庫之間程式碼複用的需求示意如圖,業務庫A需要複用業務庫B中的ServiceImpl但又不能直接引用,因此通過WMRouter載入:
- 抽取介面(或父類,後面不再重複說明)下沉到平臺層,實現類ServiceImpl實現該介面,並宣告一個Key(字串型別)。
- 呼叫方通過介面和Key,由ServiceLoader載入實現類,通過介面訪問實現類。
URI跳轉和ServiceLoader看起來似乎沒有關聯,但通訊和複用需求的本質都可以理解成路由,頁面通過URI分發跳轉時的協議是Activity+URI,在這裡ServiceLoader的協議是Interface+Key。
依賴注入
為了相容外賣獨立App和美團App外賣頻道的兩端差異,平臺層的一些介面要在兩個主工程分別實現,並注入到底層。常規Java程式碼注入的方式寫起來很繁瑣,而使用WMRouter的ServiceLoader功能可以更簡單的實現和依賴注入類似的效果。
對於WMRouter來說,所有依賴它的工程(包括主工程、業務庫、平臺庫)都是一樣的,任何一個庫想要呼叫其他庫中的程式碼,都可以通過WMRouter路由轉發。前面的通訊和複用問題,是同級的業務庫之間通過WMRouter呼叫,而依賴注入則是底層庫通過WMRouter呼叫上層庫,其本質和實現都是相同的。
ServiceLoader模組在載入實現類時提供了單例管理功能,可用於管理一些全域性的Service/Manager,例如使用者賬戶管理類UserManager
。
編譯問題
由於歷史原因,主工程作為一個沒有業務邏輯的殼工程,對業務庫卻有較多依賴,特別是對業務庫的初始化配置繁瑣,和各業務庫耦合緊密。另一方面,WMRouter跳轉的頁面、載入的實現類,需要在Application初始化時註冊到WMRouter中,也會增加主工程和業務庫的耦合。開發過程中各業務庫頻繁更新,經常出現無法編譯的問題,嚴重影響開發。
為了解決這個問題,一方面WMRouter增加了註解支援,在Activity類、ServiceLoader實現類上配置註解,就可以在編譯期間自動生成程式碼註冊到WMRouter中。
// 沒有註解時,需要在Application初始化時程式碼註冊各個頁面,耦合嚴重
register("/home", HomeActivity.class);
register("/order", OrderListActivity.class);
register("/shop", ShopActivity.class)
register("/account", MyAccountActivity.class);
register("/address", MyAddressActivity.class);
// ...
// 增加註解後,只需要在各個Activity上通過註解配置即可
@RouterUri(path = "/shop")
public class ShopActivity extends BaseActivity {
}
另一方面,ServiceLoader還支援指定介面載入所有實現類,主工程可以通過統一介面,載入各個業務庫中所有實現類並進行初始化,最終實現和業務庫的徹底隔離。
開發過程中,各個業務庫可以像外掛一樣按需整合到主工程,能大幅減少不能編譯的問題,同時由於編譯時可以跳過不需要的業務庫,編譯速度也能得到提高。
WMRouter的推廣
在WMRouter解決了外賣C端App的各種問題後,發現公司內甚至公司外的其他App也遇到了相似的問題和需求,於是決定對WMRouter進行推廣和開源。
由於WMRouter是一個開放式元件化框架,UriRequest可以存放任意資料,UriHandler、UriInterceptor可以完全自定義,不同的UriHandler可以任意組合,具有很大的靈活性。但過於靈活容易導致易用性的下降,即使對於最常規最簡單的應用,也需要複雜的配置才能完成功能。
為了在靈活性與易用性之間平衡,一方面,WMRouter對包結構進行了合理的劃分,核心介面和實現類提供基礎通用能力,儘可能保留最大的靈活性;另一方面,封裝了一系列通用實現類,並組合成一套預設實現,從而滿足絕大多數常規使用場景,儘可能降低其他App的接入成本,方便推廣。
總結
目前業界已有的一些Android路由框架,不能滿足外賣C端App在開發過程中的實際需要,因此我們開發了WMRouter路由框架。借鑑網路請求的思想,設計了基於UriRequest、UriHandler、UriInterceptor的URI分發機制,在保證功能靈活強大的同時,又儘可能的降低了使用難度;另一方面,借鑑SPI的設計思想、Java和美團平臺的ServiceLoader實現,開發了自己的ServiceLoader模組,解決外賣平臺化過程中的四個問題(通訊問題、複用問題、依賴注入、編譯問題)。在經過了近一年的不斷迭代完善後,WMRouter已經成為美團多個App中的核心基礎元件之一。
參考資料
相關推薦
WMRouter:美團外賣Android開源路由框架
WMRouter是一款Android路由框架,基於元件化的設計思路,功能靈活,使用也比較簡單。 WMRouter最初用於解決美團外賣C端App在業務演進過程中的實際問題,之後逐步推廣到了美團其他App,因此我們決定將其開源,希望更多技術同行一起開發,應用到更廣泛的場
iOS App冷啟動治理:來自美團外賣的實踐
一、背景 冷啟動時長是App效能的重要指標,作為使用者體驗的第一道“門”,直接決定著使用者對App的第一印象。美團外賣iOS客戶端從2013年11月開始,歷經幾十個版本的迭代開發,產品形態不斷完善,業務功能日趨複雜;同時外賣App也已經由原來的獨立業務App演進成為一個平臺App,陸續接入了閃購、跑腿等其他
美團外賣:日訂單量超1600萬的自動化業務運維之路
背景 美團外賣業務在網際網路行業是非常獨特的,不僅流程複雜——從使用者下單、商家接單到配送員接單、交付,而且壓力和流量在午、晚高峰時段非常集中。同時,外賣業務的增長非常迅猛,自2013年11月上線到最近峰值突破1600萬,還不到4年。在這種情況下,一旦出現事故,單純靠人工排查解決問題,存在較多的侷限
Android仿美團外賣點菜聯動列表
Android高仿美團外賣點菜聯動列表效果 最近專案中有一個新增購物車的需求,需要做成美團外賣點菜聯動ListView的效果,可能有的朋友覺得這很簡單,不就是2個Listview點選事件聯動處理機制嗎?沒錯,基本思路就是這樣子,只是美團外賣點菜效果上有一種根據
美團外賣商家獲取訂單-signToken取值
post ima gsl ffffff hid eve extend -1 ati 所需工具: findller chrome 獲取外賣歷史訂單地址為: http://e.waimai.meituan.com/v2/order/history/r/query?getNe
移動Web APP開發之實戰美團外賣 高清無密 百度網盤
管理 如何 第6章 代碼管理 view 優化 移動web webp flex 第1章 課程介紹 通過課程介紹,了解學習課程的必要性,所包含的知識點,課程安排,學習前提,課程收獲,快速全面了解課程。 1-1 課程導學 第2章 移動web硬知識點 本章主要講解移動web開發中必
移動Web APP開發之實戰美團外賣
第1章 課程介紹 通過課程介紹,瞭解學習課程的必要性,所包含的知識點,課程安排,學習前提,課程收穫,快速全面瞭解課程。 1-1 課程導學 第2章 移動web硬知識點 本章主要講解移動web開發中必要掌握的基本知識,是進行後續學習的前提。從概述到開發除錯方法
WeGeek Talk | 美團外賣
今天前來專欄分享的極客,是來自美團外賣的小程式前端團隊。 在 2017 年 1 月 9 日,美團外賣作為首批小程式正式上線,截止到目前,美團外賣小程式 DAU 已近千萬。但事實上,美團外賣早期時更多的是主打手機網頁端,在美團外賣的小程式剛上線時並沒有過多去維護,之後才與微信官方有了更多交流。
最新移動Web APP開發之實戰美團外賣
1.1 在設定中勾中Build project automatically 1.2 使用快捷鍵Ctrl + shift + alt + /,開啟Maintenance操作面板,選擇Registry,開啟Registry操作面板 1.3 找到並勾線"compiler.aut0mak
下午不知道吃什麼?用Python爬取美團外賣評論幫你選餐!
一、介紹 朋友暑假實踐需要美團外賣APP評論這一份資料,一開始我想,這不就抓取網頁原始碼再從中提取資料就可以了嗎,結果發現事實並非如此,情況和之前崔大講過的分析Ajax來抓取今日頭條街拍美圖類似,都是通過非同步載入的方式傳輸資料,不同的是這次的是通過JS傳輸,其他的基本思路基本一致,希望那些資料
美團外賣iOS App冷啟動治理
一、背景 冷啟動時長是App效能的重要指標,作為使用者體驗的第一道“門”,直接決定著使用者對App的第一印象。美團外賣iOS客戶端從2013年11月開始,歷經幾十個版本的迭代開發,產品形態不斷完善,業務功能日趨複雜;同時外賣App也已經由原來的獨立業務App演進成為一個平臺App,陸續接入了閃購、跑腿等其他
訂餐外賣網站原始碼模板多使用者帶後臺 仿餓了麼美團外賣o2o
系統簡介: 網上訂餐系統,是石家莊晟訊網路科技有限公司為滿足眾多餐飲外賣企業的迫切需要,開發定製的一款成熟的“B2C網上訂餐系統”。目前已經運用到全國各地,網上點餐系統致力於幫助專業從事餐飲外賣企業或有外賣業務的餐飲企業快速部署外賣訂餐系統,拓展網路外賣訂餐業務
移動WebAPP開發之實戰美團外賣視訊教程
第1章 課程介紹通過課程介紹,瞭解學習課程的必要性,所包含的知識點,課程安排,學習前提,課程收穫,快速全面瞭解課程。1-1 課程導學第2章 移動web硬知識點本章主要講解移動web開發中必要掌握的基本知識,是進行後續學習的前提。從概述到開發除錯方法,以及viewport視窗概念和原理的講解,在到移動web開發
微信小程式(初學篇)——仿美團外賣
初識小程式,為它的小巧玲瓏所吸引,不由得心血來潮。這不正是使用者所需要的嗎?既方便快捷,又不佔手機記憶體。所以我下定決心一定要做出一個自己的小程式,然後賺錢、賺錢、賺錢...當然現在只是學習階段,所以先仿一個高階產品來挑戰自我吧。說到高階,自然然而的就想到了美團。之後噼裡啪
爬蟲實戰----美團外賣商家資料介面分析
本文發表於2017年11月6號,不保證其在之後的時間仍適用,只作例子分享 準備工作 抓包工具:Fiddler,Firebug等工具,此文使用Chrome瀏覽器自帶的抓包工具 介面分析(從H5端入手) 首先進入美團外賣h5的商家列表頁
日訂單超1000萬,美團外賣是如何設計廣告推送系統的?
在 2013 年,美團一直靠資本推動拉新,到 2015 年,為了達到收支平衡,美團開始考慮商業變現。從 2016 年初到 2017 年,美團針對商業變現做了兩套廣告系統,並上線投入使用。本文由美團外賣商業技術負責人王興星與大家分享外賣業務合理變現系統的設計過程及相關經驗
【筆記】從架構到演算法,詳解美團外賣訂單分配內部機制
1)採用迭代的方式,通過訂單分配優化演算法進行初始的訂單分配,然後通過騎手路徑優化演算法獲取各騎手的最佳行駛路線,進而,訂單分配優化演算法根據騎手路徑優化結果調整分配方案。這兩個層次不斷反覆迭代,最終獲得比較滿意的解 (adsbygoogle = window.adsbygoogle
美團外賣訂單中心的演進
前言 美團外賣從2013年9月成交第一單以來,已走過了三個年頭。期間,業務飛速發展,美團外賣由日均幾單發展為日均500萬單(9月11日已突破600萬)的大型O2O網際網路外賣服務平臺。平臺支援的品類也由最初外賣單品拓展為全品類。 隨著訂單量的增長、業務複雜度的提升,外賣訂單系統也在不斷演變進化,從早期
接入美團外賣 php後臺接入美團外賣 laravel 常見問題
美團外賣請求的timestamp要求時間戳要精確到毫秒 不然會一直報時間戳過期的美團外賣回撥地址(ngrok 內網對映post請求不行,博主就被坑了)任何回撥地址都在本地postman上自己呼叫一下第一步申請開發者,確認已經申請成功,上面就是沒完全成功有賬號的但是還有其他在
詳解美團外賣訂單分配內部機制
公司做外賣配送,正好又在做系統派單這塊,遇到很多很多的難點,某日看到了這篇文章,從理論的角度介紹了訂單內部分派機制。所以給抄了過來! 美團點評日前完成最新一輪融資,估值達到300億美元。此輪融資後將會在人工智慧、無人配送等前沿技術研發上加大投入。但我們並