Automated Page Speed Measurement Plugin for Android Apps
The Meituan Android team built an automated, non‑intrusive page‑speed plugin that injects SDK calls at compile time via a Gradle Transform, measures cold‑start, first render, network request and second render for Activities and Fragments—including ViewPager lazy loading—fetches real‑time config from a server and reports metrics to their monitoring platform.
With the rapid growth of mobile Internet, user experience increasingly depends on fast page loading. The Meituan Android team needed a way to monitor loading speed without manually inserting timing code into each page.
Existing solutions required developers to add code in Application.onCreate(), Activity lifecycle methods, custom parent Views, or maintain a local JSON configuration. These approaches suffered from inaccurate cold‑start measurement, special‑case handling (e.g., ViewPager+Fragment lazy loading), high maintenance cost, and the need for manual configuration updates.
Target solution provides automatic code injection, supports both Activity and Fragment pages, correctly measures cold start from the Application constructor, and fetches configuration from a server in real time.
Implementation steps :
Define speed metrics (cold start, first render, initial network request, second render).
Use an XML configuration file to list pages (by class name) and their initial API endpoints.
Build an SDK that manages the config, creates page objects, records timestamps, and reports data.
Automate injection via a Gradle Transform plugin using Javassist to insert SDK calls at compile time.
Handle edge cases such as ViewPager lazy loading and fragment view creation.
Speed definitions :
Cold start: from Application creation to the first HomeActivity render.
First render: from onCreate() of Activity/Fragment to the first draw completion.
Initial network request: time from the first request start to the last request finish for the page.
Second render: from the end of all initial requests to the second draw completion.
Configuration example (XML):
<page id="HomeActivity" tag="1">
<api id="/api/config"/>
<api id="/api/list"/>
</page>
<page id="com.test.MerchantFragment" tag="0">
<api id="/api/test1"/>
</page>Cold‑start timing is recorded in the Application constructor and passed to the SDK during initialization:
public MyApplication() {
super();
coldStartTime = SystemClock.elapsedRealtime();
}
public void onCreate() {
...
AutoSpeed.getInstance().init(this, coldStartTime);
}Page start timing is injected into Activity/Fragment onCreate() and setContentView() (or the AppCompat delegate) to call AutoSpeed.getInstance().onPageCreate(this) and wrap the root view with a custom AutoSpeedFrameLayout that records dispatchDraw():
class AutoSpeedFrameLayout extends FrameLayout {
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
AutoSpeed.getInstance().onPageDrawEnd(pageKey);
}
}Network request timing uses an OkHttp interceptor and a Retrofit callback wrapper to mark request start and end:
public class AutoSpeedRetrofitInterceptor implements Interceptor {
public Response intercept(Chain chain) throws IOException {
AutoSpeed.getInstance().onApiLoadStart(chain.request().url());
return chain.proceed(chain.request());
}
}
public class AutoSpeedRetrofitCallback<T> implements Callback<T> {
public void onResponse(Call<T> call, Response<T> response) {
AutoSpeed.getInstance().onApiLoadEnd(call.request().url());
delegate.onResponse(call, response);
}
public void onFailure(Call<T> call, Throwable t) {
AutoSpeed.getInstance().onApiLoadEnd(call.request().url());
delegate.onFailure(call, t);
}
}Automation via Gradle Transform inserts the above SDK calls into generated class files. For Activities, it modifies onCreate() and all overloads of setContentView(). For Fragments, it wraps the view returned by onCreateView() and injects timing into onCreate() and onViewCreated().
Handling ViewPager lazy loading adds listeners ( OnPageChangeListener) that record the time when a page becomes visible ( onPageSelected and onPageScrolled) and subtract this waiting period from the first‑ and second‑render calculations.
All timestamps are finally aggregated in PageObject, which computes total load time, initial draw time, and final draw time, then reports the metrics to the monitoring platform.
Conclusion the non‑intrusive automated speed testing plugin is now used in production, providing real‑time performance data that helps the team continuously optimize page load speed without manual instrumentation.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Meituan Technology Team
Over 10,000 engineers powering China’s leading lifestyle services e‑commerce platform. Supporting hundreds of millions of consumers, millions of merchants across 2,000+ industries. This is the public channel for the tech teams behind Meituan, Dianping, Meituan Waimai, Meituan Select, and related services.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
