קל לארגן דפים בעזרת אוספים
אפשר לשמור ולסווג תוכן על סמך ההעדפות שלך.
בניגוד לרוב הבדיקות של ממשק המשתמש ב-Android, הבדיקות של Macrobenchmark פועלות בתהליך נפרד
מהאפליקציה עצמה. הדבר נדרש כדי לאפשר דברים כמו הפסקת
עיבוד של אפליקציה והידור מקוד בייט של DEX לקוד מכונה.
אפשר לשפר את מצב האפליקציה באמצעות ספריית UIAutomator או ממשק אחר
מנגנונים שיכולים לשלוט באפליקציית היעד מתוך תהליך הבדיקה.
אי אפשר להשתמש ב-Espresso או ב-ActivityScenario כדי ליצור
מאקרובנצ'מרק, כי הן מצפה לפעול בתהליך משותף עם האפליקציה.
בדוגמה הבאה תמצאו מזהה של משאב RecyclerView, וגם
גולל למטה כמה פעמים:
Kotlin
@TestfunscrollList(){benchmarkRule.measureRepeated(// ...setupBlock={// Before starting to measure, navigate to the UI to be measuredvalintent=Intent("$packageName.RECYCLER_VIEW_ACTIVITY")startActivityAndWait(intent)}){valrecycler=device.findObject(By.res(packageName,"recycler"))// Set gesture margin to avoid triggering gesture navigation// with input events from automation.recycler.setGestureMargin(device.displayWidth/5)// Scroll down several timesrepeat(3){recycler.fling(Direction.DOWN)}}}
@TestpublicvoidscrollList(){benchmarkRule.measureRepeated(// .../* setupBlock */scope->{// Before measuring, navigate to the UI to be measured.valintent=Intent("$packageName.RECYCLER_VIEW_ACTIVITY")scope.startActivityAndWait();returnUnit.INSTANCE;},/* measureBlock */scope->{UiDevicedevice=scope.getDevice();UiObject2recycler=device.findObject(By.res(scope.getPackageName(),"recycler"));// Set gesture margin to avoid triggering gesture navigation// with input events from automation.recycler.setGestureMargin(device.getDisplayWidth()/5);// Fling the recycler several times.for(inti=0;i<3;i++){recycler.fling(Direction.DOWN);}returnUnit.INSTANCE;});}
נקודת ההשוואה לא צריכה לגלול בממשק המשתמש. במקום זאת, היא יכולה להריץ
אנימציה, למשל. הוא גם לא צריך להשתמש באוטומציה של ממשק המשתמש
ספציפית. היא אוספת מדדי ביצועים כל עוד הפריימים
שמערכת התצוגה יצרה, כולל פריימים שהופקו על ידי Jetpack Compose.
לנווט לחלקים פנימיים של האפליקציה
לפעמים רוצים ליצור נקודת השוואה לחלקים באפליקציה שלא קשורים באופן ישיר
מבחוץ. לדוגמה, גישה לפעילויות פנימיות
שמסומנים ב-exported=false, עוברים אל Fragment או מחליקים
חלק מממשק המשתמש שלכם. צריך לעבור לנקודות ההשוואה האלה באופן ידני
לחלקים של האפליקציה כמו משתמש.
כדי לנווט באופן ידני, צריך לשנות את הקוד בתוך setupBlock{} כך שיכיל את
האפקט הרצוי, כמו הקשה על לחצן או החלקה. measureBlock{} מכיל
רק את המניפולציה של ממשק המשתמש שרוצים שתשמש כנקודת השוואה בפועל:
Kotlin
@TestfunnonExportedActivityScrollList(){benchmarkRule.measureRepeated(// ...setupBlock=setupBenchmark()){// ...}}privatefunsetupBenchmark():MacrobenchmarkScope.()->Unit={// Before starting to measure, navigate to the UI to be measuredstartActivityAndWait()// click a button to launch the target activity.// While we use button text here to find the button, you could also use// accessibility info or resourceId.valselector=By.text("RecyclerView")if(!device.wait(Until.hasObject(selector),5_500)){fail("Could not find resource in time")}vallaunchRecyclerActivity=device.findObject(selector)launchRecyclerActivity.click()// wait until the activity is showndevice.wait(Until.hasObject(By.clazz("$packageName.NonExportedRecyclerActivity")),TimeUnit.SECONDS.toMillis(10))}
@TestpublicvoidscrollList(){benchmarkRule.measureRepeated(// .../* setupBlock */scope->{// Before measuring, navigate to the default activity.scope.startActivityAndWait();// Click a button to launch the target activity.// While you use resourceId here to find the button, you can also// use accessibility info or button text content.UiObject2launchRecyclerActivity=scope.getDevice().findObject(By.res(packageName,"launchRecyclerActivity"))launchRecyclerActivity.click();// Wait until activity is shown.scope.getDevice().wait(Until.hasObject(By.clazz("$packageName.NonExportedRecyclerActivity")),10000L)returnUnit.INSTANCE;},/* measureBlock */scope->{// ...});}
דוגמאות התוכן והקוד שבדף הזה כפופות לרישיונות המפורטים בקטע רישיון לתוכן. Java ו-OpenJDK הם סימנים מסחריים או סימנים מסחריים רשומים של חברת Oracle ו/או של השותפים העצמאיים שלה.
עדכון אחרון: 2025-09-09 (שעון UTC).
[[["התוכן קל להבנה","easyToUnderstand","thumb-up"],["התוכן עזר לי לפתור בעיה","solvedMyProblem","thumb-up"],["סיבה אחרת","otherUp","thumb-up"]],[["חסרים לי מידע או פרטים","missingTheInformationINeed","thumb-down"],["התוכן מורכב מדי או עם יותר מדי שלבים","tooComplicatedTooManySteps","thumb-down"],["התוכן לא עדכני","outOfDate","thumb-down"],["בעיה בתרגום","translationIssue","thumb-down"],["בעיה בדוגמאות/בקוד","samplesCodeIssue","thumb-down"],["סיבה אחרת","otherDown","thumb-down"]],["עדכון אחרון: 2025-09-09 (שעון UTC)."],[],[],null,["# Control your app from Macrobenchmark\n\nUnlike most Android UI tests, Macrobenchmark tests run in a separate process\nfrom the app itself. This is necessary to enable things like stopping the\napp process and compiling from DEX bytecode to machine code.\n\nYou can drive your app's state using the [UIAutomator library](/training/testing/ui-automator) or other\nmechanisms that can control the target app from the test process.\nYou can't use [Espresso](/training/testing/espresso) or [`ActivityScenario`](/reference/androidx/test/core/app/ActivityScenario) for\nMacrobenchmark because they expect to run in a shared process with the app.\n\nThe following example finds a [`RecyclerView`](/reference/androidx/recyclerview/widget/RecyclerView) using its resource ID and\nscrolls down several times: \n\n### Kotlin\n\n```kotlin\n@Test\nfun scrollList() {\n benchmarkRule.measureRepeated(\n // ...\n setupBlock = {\n // Before starting to measure, navigate to the UI to be measured\n val intent = Intent(\"$packageName.RECYCLER_VIEW_ACTIVITY\")\n startActivityAndWait(intent)\n }\n ) {\n val recycler = device.findObject(By.res(packageName, \"recycler\"))\n // Set gesture margin to avoid triggering gesture navigation\n // with input events from automation.\n recycler.setGestureMargin(device.displayWidth / 5)\n\n // Scroll down several times\n repeat(3) { recycler.fling(Direction.DOWN) }\n }\n}https://github.com/android/performance-samples/blob/570221d3f49d49e45af7970c04c1fe3a72d6df33/MacrobenchmarkSample/macrobenchmark/src/main/java/com/example/macrobenchmark/benchmark/frames/FrameTimingBenchmark.kt#L44-L70\n```\n\n### Java\n\n```java\n@Test\npublic void scrollList() {\n benchmarkRule.measureRepeated(\n // ...\n /* setupBlock */ scope -\u003e {\n // Before measuring, navigate to the UI to be measured.\n val intent = Intent(\"$packageName.RECYCLER_VIEW_ACTIVITY\")\n scope.startActivityAndWait();\n return Unit.INSTANCE;\n },\n /* measureBlock */ scope -\u003e {\n UiDevice device = scope.getDevice();\n UiObject2 recycler = device.findObject(By.res(scope.getPackageName(), \"recycler\"));\n\n // Set gesture margin to avoid triggering gesture navigation\n // with input events from automation.\n recycler.setGestureMargin(device.getDisplayWidth() / 5);\n\n // Fling the recycler several times.\n for (int i = 0; i \u003c 3; i++) {\n recycler.fling(Direction.DOWN);\n }\n\n return Unit.INSTANCE;\n }\n );\n}\n```\n\nYour benchmark doesn't have to scroll the UI. Instead, it can run an\nanimation, for example. It also doesn't need to use UI Automator\nspecifically. It collects performance metrics as long as frames are being\nproduced by the view system, including frames produced by [Jetpack Compose](/jetpack/compose).\n| **Note:** When accessing UI objects, specify the `packageName`, because the tests run in a separate process.\n\nNavigate to internal parts of the app\n-------------------------------------\n\nSometimes you want to benchmark parts of your app that aren't directly\naccessible from outside. This might be, for example, accessing inner Activities\nthat are marked with [`exported=false`](/guide/topics/manifest/activity-element#exported), navigating to a [`Fragment`](/reference/android/app/Fragment), or swiping\nsome part of your UI away. The benchmarks need to manually navigate to these\nparts of the app like a user.\n\nTo manually navigate, change the code inside `setupBlock{}` to contain the\neffect you want, such as button tap or swipe. Your `measureBlock{}` contains\nonly the UI manipulation you want to actually benchmark: \n\n### Kotlin\n\n```kotlin\n@Test\nfun nonExportedActivityScrollList() {\n benchmarkRule.measureRepeated(\n // ...\n setupBlock = setupBenchmark()\n ) {\n // ...\n }\n}\n\nprivate fun setupBenchmark(): MacrobenchmarkScope.() -\u003e Unit = {\n // Before starting to measure, navigate to the UI to be measured\n startActivityAndWait()\n\n // click a button to launch the target activity.\n // While we use button text here to find the button, you could also use\n // accessibility info or resourceId.\n val selector = By.text(\"RecyclerView\")\n if (!device.wait(Until.hasObject(selector), 5_500)) {\n fail(\"Could not find resource in time\")\n }\n val launchRecyclerActivity = device.findObject(selector)\n launchRecyclerActivity.click()\n\n // wait until the activity is shown\n device.wait(\n Until.hasObject(By.clazz(\"$packageName.NonExportedRecyclerActivity\")),\n TimeUnit.SECONDS.toMillis(10)\n )\n}https://github.com/android/performance-samples/blob/570221d3f49d49e45af7970c04c1fe3a72d6df33/MacrobenchmarkSample/macrobenchmark/src/main/java/com/example/macrobenchmark/benchmark/frames/NonExportedActivityBenchmark.kt#L48-L94\n```\n\n### Java\n\n```java\n@Test\npublic void scrollList() {\n benchmarkRule.measureRepeated(\n // ...\n /* setupBlock */ scope -\u003e {\n // Before measuring, navigate to the default activity.\n scope.startActivityAndWait();\n\n // Click a button to launch the target activity.\n // While you use resourceId here to find the button, you can also\n // use accessibility info or button text content.\n UiObject2 launchRecyclerActivity = scope.getDevice().findObject(\n By.res(packageName, \"launchRecyclerActivity\")\n )\n launchRecyclerActivity.click();\n\n // Wait until activity is shown.\n scope.getDevice().wait(\n Until.hasObject(By.clazz(\"$packageName.NonExportedRecyclerActivity\")),\n 10000L\n )\n\n return Unit.INSTANCE;\n },\n /* measureBlock */ scope -\u003e {\n // ...\n }\n );\n}\n```\n\nRecommended for you\n-------------------\n\n- Note: link text is displayed when JavaScript is off\n- [Writing a Macrobenchmark](/topic/performance/benchmarking/macrobenchmark-overview)\n- [Capture Macrobenchmark metrics](/topic/performance/benchmarking/macrobenchmark-metrics)\n- [Microbenchmark](/topic/performance/benchmarking/microbenchmark-overview)"]]