Today, we’ll explore one interesting aspect of the repetition rule of our programming language. To solve the puzzle, we’ll use the same two rules as last time, the Q rule (quotation) and the R rule (repetition). In case you need to refresh your memory, the rules are described here.
From the rules definition you know that for any statement x the following is true:
RQx = xx.
But is there such a statement x for which the following is true?:
Rx = xx.
Solution To see the correct solution, click 'Show' button... SelectShow
The correct answer is: RQRQ
To verify: Rx = RRQRQ = RR(Q(RQ)) = 2*2*(RQ) = 2*(RQRQ) = RQRQRQRQ = (RQRQ)(RQRQ) = xx
… the parentheses and numeral 2 and multiplication sign (*) are not part of the language, they are just used for clarity.
OK, now the question: how shall I figure this out (well, guessing is also a method, but let’s be more deterministic)?
So think about x and how it should look like.
Let’s start (as always), with idea of x = Qy
Then Rx = RQy = yy.
This doesn’t work since x is not equal to y (x is always one letter — the letter “Q” — longer).
OK, let’s explore the idea of x = RQy
Now Rx = RRQy = yyyy.
Since we need Rx = xx, and we get Rx = yyyy, this can actually work if x = yy.
We started with x = RQy, and need x = yy.
Therefore RQy = yy.
Looks familiar, right?
This works for y = RQ.
So the x we were looking for is RQy = RQRQ.
“So! Many! Views!” — that’s exactly what I felt when we started the process of optimizing Firefox for Android. Compound Drawables was pure magic. It reduced a lot of views in the home page. But we wanted to see where all it could be used. The custom menu was a good choice. To stand out from other menus, but still feel like Android menu, we added the images to the menu. This required re-writing the entire menu management ourselves. Also, some menu items are checkable and some others can have a sub menu. We added an indicator on the right for the same. The final layout had no less than 8 views to manage the image, text and the indicator along with the variable padding in between them.
How do we reduce the views in this menu? This menu is going to exist for the entire life time of the app (at this point of writing, even though they use a list view, the individual rows aren’t cleared every time the menu is closed). To start optimizing, let’s look at how the original menu layout was.<LinearLayout> <!-- left-most padding --> <View android:layout_width="10dp"/> <!-- icon --> <ImageView /> <!-- menu item name --> <TextView /> <!-- right Indicator --> <FrameLayout> <!-- tick --> <CheckBox /> <!-- more indicator --> <ImageView /> </FrameLayout> <!-- right-most padding --> <View android:layout_width="10dp"/> </LinearLayout>
The low hanging fruit here is to combine the ImageView for the icon with the TextView. That reduces one of the two views. The left and right most padding are interesting cases. The TextView by itself cannot have a standard margin. This would push the text more inside, if the icon or the right indicator is present, but will look right without them. But, that’s not the intended design. The parent LinearLayout can have a padding. However, this layout file actually had a <merge/> tag as the parent, as the layout could be inflated into any ViewGroup on demand. Now, since the left image is now made a compound drawable, the padding can be merged with the TextView. We are left with the right indicator (3 views) and an empty view for padding.
The interesting thing with compound drawables is that they support states. The state of the TextView is duplicated to the compound drawables too. If there is a way to combine the CheckBox and the ImageView as a single drawable, the entire right indicator could be made a compound drawable. How do we do that? The easiest way is to have custom states. A typical state list for the right indicator would look like:<selector> <!-- more indicator --> <item app:state_more="true" android:drawable="@drawable/more_indicator"/> <!-- checked state --> <item app:state_more="false" android:state_checkable="true" android:state_checked="true" android:drawable="@drawable/check_mark"/> <!-- unchecked state --> <item app:state_more="false" android:state_checkable="true" android:state_checked="false" android:drawable="@drawable/check_box"/> <!-- default state --> <item android:drawable="@android:color/transparent"/> </selector>
The right side of the TextView is shrunk to a single image with multiple states. This can be the android:drawableRight of the text. So, how many views do we have for the menu item?<TextView android:drawableLeft="@drawable/_assigned_by_code_" android:drawableRight="@drawable/_right_indicator_selector_" android:paddingLeft="10dp" android:paddingRight="10dp"/>
And that’s how we optimize Firefox on Android! One view at a time!
Yesterday makes it a full year since Creative Commons and Mozilla contributor Bassel Khartibil was imprisoned by the Syrian regime. Last July a public campaign was launched, and Mozilla participated .
This public campaign to #freebassel may have played a significant role in getting Bassel moved from a military intelligence to a civilian prison with visitation rights.
We continue to urge support for the #freebassel campaign by visiting the website, tweeting about Bassel’s case (#freebassel), or attending an event in his honor.