Deep analysis of Android's custom layouts
As long as you have written the Android program, you must have used the Android platform built in several layouts--relativelayout, LinearLayout, Framelayout and so on. They can help us build the Android UI well.
These built-in layouts already offer a lot of handy widgets, but in many cases you still need to customize your layout.
To summarize, the custom layout has two major advantages:
Make your UI display more efficient by reducing the use of the view and traversing the layout elements more quickly;
You can build a UI that cannot be implemented by an existing view.
In this blog post, I'll implement four different custom layouts and compare their pros and cons. They are: Composite view, custom composite View,flat custom view, and async custom views.
These code implementations can be found in the Android-layout-samples project on my GitHub. The app uses the four custom layouts mentioned above to achieve the same UI effect. They use Picasso to load pictures. The app's UI is just a simplified version of Twitter timeline-no interaction, only layout.
Well, let's start with the most common custom layouts: Composite view.
Composite View
Composite Views (also known as compound views) is the simplest of many ways to combine multiple views into a reusable UI component. The process of implementing this method is as follows:
Inherits the associated built-in layout.
Populate the constructor with a merge layout.
Initializes the member variable and points to the internal view through Findviewbyid ().
Add a custom API to query and update the view's status.
Tweetcompositeviewcode is a composite view. It inherits from the Relativelayout, populates the Tweet_composite_layout.xmlcode layout file, and finally exposes the update () method to the outside world to update its status in Adaptercode.
Custom Composite View
The above mentioned Tweetcompositeview this realization way to satisfy most of the situation. But it's not going to happen. Let's say you want to reduce the number of child views now, making the layout element easier to work with.
This time we can look back and see, although composite views are easier to implement, there is still a lot of overhead involved in using these built-in layouts-especially in the more complex containers of linearlayout and relativelayout. Due to the implementation of the built-in layout of the Android platform, in a single layout element traversal, the system needs to handle many layout combinations and sub-views of the--linearlayout Layout_weight properties are common examples.
So you can tailor a set of sub-view calculations and positioning logic for your app, so you can optimize your UI a lot. This is the custom composite view I'm going to introduce next.
As the name implies, a custom composite view is a composite view that overrides the Onmeasure () and OnLayout () methods. So instead of inheriting relativelayout from the previous composite view, now we need to take a step further--inheriting the more abstract viewgroup.
Tweetlayoutviewcode is achieved through this technology. Note that now this implementation does not inherit the linearlayout like Tweetcomposiveview, which avoids the use of the Layout_weightcode attribute.
This much-used process calculates the measurespec of each sub-view by ViewGroup's Measurechildwithmargins () method and the Getchildmeasurespec () method behind it.
Tweetlayoutview does not handle all possible layout combinations correctly, but it does not have to be. We definitely need to optimize our custom layouts based on specific needs, which allows us to write simple and efficient layout code.
Flat Custom View
As you see, custom composite views can be implemented simply by using the ViewGroup API. Most of the time, this implementation is available to meet our needs.
But we want to do something further-to optimize the key UI in our application, such as ListViews, Viewpager, and so on. What if we combined all of the Tweetlayoutview sub-views into a single, custom view and unified management? This is what we are going to discuss next flat custom view--see the picture below.
Custom COMPOSITE View on the left, flat custom view on the right
Flat custom view is a fully customizable view that is fully responsible for the calculation, placement, and drawing of the internal sub-views. So it inherits the view directly instead of the ViewGroup.
If you're looking for an example of a real-life app, it's simple-turn on the "Show layout boundaries" option in the "developer mode" of your phone, then open Twitter, Gmail, or pocket apps that use flat custom in the list UI. View
The main benefit of using flat custom view is that it can greatly compress the view level of the app, allowing for faster layout element traversal, which can ultimately reduce memory footprint.
Flat Custom view can give you the greatest freedom, as if you were painting on a piece of white paper. But this freedom comes at a price: You can't use existing view elements, such as TextView and ImageView. Yes, it's really easy to paint text on Canvas, but do you want to implement ellipsizing (that is, long text truncation)? Similarly, it is easy to paint pictures on Canvas, but how do you scale them? These restrictions also apply to touch events, accessibility, keyboard navigation, and so on.
So the bottom line of using flat custom view is that only the flat custom view is applied to the UI core of your app, and the rest is directly dependent on the view provided by the Android platform.
Tweetelementviewcode is flat custom view. To make it easier to implement it, I created a small custom view frame called UIElement. You can find it in the Canvascode bag.
UIElement provides a similar measure/layout API to the Android platform. It contains TextView and ImageView without an image interface, and these two elements contain several required features-see Textelementcode and Imageelementcode, respectively. It also has its own inflatercode to help instantiate UIElement from the layout resource file code.
Note: UIElement is still in a very early stage of development, so there are a lot of flaws, but it can be very useful in the future as UIElement evolve.
You might think that the Tweetelementview code looks simple because the actual code is inside the Tweetelementcode-actually Tweetelementview plays the managed role code.
The layout code inside the tweetelement is very similar to Tweetlayoutview ', but it does not use the same code when using Picasso to request a picture because Tweetelement does not use ImageView.
Async Custom View
It is always known that the Android UI framework is single-threaded. Such a single thread will bring some restrictions. For example, you can't traverse layout elements outside the main thread--however, this is useful for complex, dynamic UIs.
If your app is a very complex item in a ListView (like most social apps), you're likely to have a skip frame when you swipe the ListView because the ListView You need to calculate their view size code and layout code for new content that will appear in the list. The same problem will occur in gridviews,viewpagers and so on.
Is it possible to solve the above problem if we can do a layout traversal on a thread that is not yet present on the threads outside the main thread? That is, calling the measure () and layout () methods above the child view will not occupy the main thread time.
So async custom View is an experiment that allows the sub-view layout traversal to take place outside the main thread, and this idea was inspired by the video of Facebook's paperteam async node framework.
Since we never touch the UI components of the Android platform outside the main thread, we need an API to measure and lay out the contents of this view without direct access to the view. This is exactly what the UIElement framework provides to me.
Asynctweetviewcode is an async custom view. It uses a thread-safe Asynctweetelementcode factory class code to define its contents. The process is a smoothie child loader code that creates, predicts, and caches temporarily invisible asynctweetelement on a background thread (in memory for later direct use).
Of course, in implementing this asynchronous UI I compromised a bit because you didn't know how to show the layout placeholders at any height. For example, when the layout is passed asynchronously, you can only change the size of the background thread once. Therefore, when a asynctweetview is about to be displayed, it is not possible to find the right asynctweetelement in memory, and this time the framework forces a asynctweetelement code to be created on the main thread.
Also, pre-loaded logic and memory cache expiration time settings require a better implementation to ensure that the main thread uses as much of the memory as possible in the cache layout. For example, using the LRU cache code in this scenario is not a sensible option.
Despite these limitations, the initial results from using async custom view are promising. Of course I will continue to explore in this area by refactoring this UIElement framework and using other categories of UI. Let's watch it change.
Summarize
As we relate to the layout, the deeper we customize, the less reliance we can get from the Android platform. So we also want to avoid premature optimizations and complete layout customizations only in areas that do actually improve the quality and performance of your app.
This is not a black-and-white decision. There are a number of scenarios between using the platform-provided UI elements and completely customizing the two extremes-from simple composite views to complex async views. In a real-world project, you might write good apps in combination with several scenarios.
Deep analysis of Android's custom layouts