Status Update
Comments
py...@gmail.com <py...@gmail.com> #2
<transition xmlns:android="
<item android:drawable="@drawable/test_drawable_blue"/>
<item android:drawable="@drawable/test_drawable_green"/>
</transition>
where blue/green drawables look like this:
<shape
xmlns:android="
android:shape="rectangle">
<size
android:width="@dimen/drawable_large_size"
android:height="@dimen/drawable_small_size" />
<solid
android:color="@color/test_blue" />
</shape>
Then added this test:
@Test
public void testMutateTransitionDrawable() {
Drawable drawable = ResourcesCompat.getDrawable(mResources,
R.drawable.test_transition_drawable, null);
assertTrue(drawable instanceof TransitionDrawable);
Drawable mutated = drawable.mutate();
assertTrue(drawable instanceof TransitionDrawable);
assertTrue(mutated instanceof TransitionDrawable);
}
It passes on the device. Going to also try on other earlier devices a bit later in the day once they are charged.
ch...@google.com <ch...@google.com> #3
ch...@google.com <ch...@google.com> #4
ch...@google.com <ch...@google.com> #5
* Note that the function will not create a PerformanceMetricsState object if the
* Holder's `state` is null; that object is created when a [JankStats]
* object is created. This is done to avoid recording performance state if it is
* not being tracked.
However, I'm inclined to leave this loose-but-not coupling as-is. The intention is to enable any caller to get the state holder and popular it if appropriate, but not to bother wasting space and time doing so if nobody is tracking that data.
For example, we might add code to AndroidX libraries to populate state for JankStats in general. But it only makes sense doing that if someone wants that data, otherwise we are wasting time, allocations, and space on data that is unnecessary. So it makes sense to have the loose coupling that allows, say, RecyclerView to get the state object for the hierarchy and call (if state?) addState() with relevant data. But it also makes sense to have that state object only exist and be valid if someone is listening on the other end.
ap...@google.com <ap...@google.com> #6
Branch: androidx-main
commit 9a8c7dd45518e4f8c8e04776c0b7487de62ce0dc
Author: Chet Haase <chet@google.com>
Date: Mon Jul 11 17:24:18 2022
Minor changes in PerformanceMetricsState APIs for clarity
There was some confusion in some method and parameter names
in PerformanceMetricsState which have been changed for clarity.
For example, stateName/state were being set on a 'state' object,
which seemed redundant. Since they are acting as a key/value pair,
they have been changed to simply key and value. Also, getForHierarchy()
on PerformanceMetricsState returned a Holder object, not (as one might
assume) a State object, so the method name was updated to
getHolderForHierarchy(). Finally, add[SingleFrame]State was actually
replacing state, acting more like a Map than a List or Set, so the method
names were updated to 'put' instead.
Bug: 233421985
Test: Ran JankStatsTest, benchmark, unit test apps
RelNote: "Updated method and parameter names in PerformanceMetricsState
to make the results of those calls clearer."
Change-Id: I56da57b13818bf4077a64ab144222ce255f4539a
M metrics/metrics-performance/api/public_plus_experimental_current.txt
M metrics/metrics-performance/src/main/java/androidx/metrics/performance/FrameData.kt
M metrics/metrics-performance/api/restricted_current.txt
M metrics/metrics-performance/src/main/java/androidx/metrics/performance/JankStatsApi24Impl.kt
M metrics/metrics-performance/src/main/java/androidx/metrics/performance/JankStatsApi16Impl.kt
M metrics/metrics-performance/src/androidTest/java/androidx/metrics/performance/test/JankStatsTest.kt
M metrics/integration-tests/janktest/src/main/java/androidx/metrics/performance/janktest/JankAggregatorActivity.kt
M metrics/integration-tests/janktest/src/main/java/androidx/metrics/performance/janktest/MessageListFragment.kt
M metrics/integration-tests/janktest/src/main/java/androidx/metrics/performance/janktest/JankLoggingActivity.kt
M metrics/metrics-performance/src/androidTest/java/androidx/metrics/performance/test/DelayedView.kt
M metrics/metrics-benchmark/src/androidTest/java/androidx/metrics/performance/benchmark/JankStatsBenchmark.kt
M metrics/metrics-performance/src/main/java/androidx/metrics/performance/FrameDataApi31.kt
M metrics/metrics-performance/src/main/java/androidx/metrics/performance/PerformanceMetricsState.kt
M metrics/integration-tests/janktest/src/main/java/androidx/metrics/performance/janktest/SimpleLoggingActivity.kt
M metrics/metrics-performance/src/main/java/androidx/metrics/performance/FrameDataApi24.kt
M metrics/metrics-performance/api/current.txt
ch...@google.com <ch...@google.com>
py...@gmail.com <py...@gmail.com> #7
Thanks for the fixes!
I think the loose-but-not coupling is fine, it's just that I'm assuming at some point you might want to release other jetpack perf metric libs and then you'll have more places that care about tracking state. So maybe at some point there should be a "this window should track state" API.. and these pieces can be released as a tiny standalone lib. but maybe YAGNI. I'm just wondering if I'd be interested in leveraging this as well in 3rd party libs.
Regarding the holder, I'm still confused why we need to call PerformanceMetricsState.getHolderForHierarchy(view)?.state
, i.e. the holder isn't useful ever from a public API standpoint, so I why not have a PerformanceMetricsState.getForHierarchy(view)
that returns PerformanceMetricsState?
directly and keep the Holder class internal?
ch...@google.com <ch...@google.com> #8
As for the Holder, it is possible that it will become null later, if the app stops tracking. The reason for the Holder is to have relevant information at the time when you want to inject state, not to cache something that might be obsolete later. Or, for another example, it may be initially null when you first get the Holder, but the next time that code is run, there is an attached JankStats, thus it is active. If you had cached the initial result, then you might never populate state, whereas if you get it at the time when you should inject it, you know whether someone is listening or not.
Description
PerformanceMetricsState.getForHierarchy
returns aMetricsStateHolder
which is just a wrapper aroundPerformanceMetricsState?
.As I started using it, I did this:
So.. I'm getting a state, then getting a state from it or maybe not, and if I do have a state then I can add a state to it!
The other thing that's a bit weird about this is how
PerformanceMetricsState
is a separate class but it's directly coupled to JankState, i.e.MetricsStateHolder.state
will always be set if I already calledJankState.createAndTrack()
for that window, but it'll be null if I didn't. This conditional nullability isn't super clear.Suggestions:
MetricsStateHolder
and havinggetForHierarchy
directly returnPerformanceMetricsState?
PerformanceMetricsState.create()
function that JankStat is calling, and havingMetricsStateHolder.getForHierarchy()
automatically create it on first call. Making the coupling more explicit might mean making a PerformanceMetricsState instance directly available on a JankState instance.