When developing for Android, you always need to be alert. Step to the left / step to the right - and now another hour has passed after the debug. The cuvettes can be anything from normal bugs in the SDK and ending with non-obvious method names with context-sensitive results (yes, 
Fragment.getFragmentManager () , I mean you).
In the 
previous article , we described cuvettes “on the surface” of the SDK, into which it is very easy to please. This time the cuvettes will be deeper, wiser and more specific. There will also be a few points related to 
Retrofit 2 & 
Gson .

1. GridLayout does not respond to layout_weight
Situation
Sometimes it happens that the usual way to create an object with a heap does not fit:
Such a situation could be, for example, 
landscape form mapping. I would like in this case to have something like this:
How to make the same alignment 50 to 50? There are several 
basic approaches :
However, they all have their drawbacks:
- The abundance of LinearLayout leads to xml's monstrosity , and it leads to the death of seals.
- RelativeLayout complicates the change in the future (swap a few lines in the form or add a separator will be the one more task. I’m completely silent about View.setVisibility (View.GONE ).
- Well, nobody uses TableLayout at all ... or uses it, but rarely. I do not know such people.
Moreover, it is often necessary to use the magic number 
0dp & weight = 1 to achieve a flexible design. Neither 
TableLayout nor 
RelativeLayout will help you here. When you first try to use something like 
TextView.setEllipsize () , problems and pain will begin.
And then you probably noticed that I missed another element. It would seem that 
GridLayout comes to the rescue, but it also turns out to be useless due to the fact that it does not support the 
layout_weight property. So what to do?
')
Decision
Until now, there was really nothing to do - either suffer with 
RelativeLayout , or use 
LinearLayout , or fill in everything programmatically (for especially perverted ones).
However, since version 21, 
GridLayout has finally begun to support the 
layout_weight property and, most importantly, this change was added to 
AppCompat as 
android.support.v7.widget.GridLayout !
By the time I found out about this (and generally that the usual 
GridLayout wanted to weigh on my 
weight ), I spent at least a week trying to understand why my 
layout swam to the right (like 
this ). Perhaps this is one of the most important innovations, which, for some reason, remained without proper attention. Fortunately, stackoverflow ( 
1 , 
2 ) responses are already beginning to be added.
I also advise you to look at the page to the new 
PercentRelativeLayout and 
PercentFrameLayout - this is really a bomb. The name speaks for itself and allows you to make a highly responsive design. iOS'niki appreciate. And oh yeah, it is in 
AppCompat .
Situation
Once I wanted to write my 
PresenterManager as a singleton (hello from 
MVP ). In order to remove 
Presenters in time, I used 
Activity.isFinishing () , collecting 
id Presenter 's of activites and deleting them with it. Naturally, this method worked poorly in the case of 
NavigationView - fragments changed through 
FragmentTransaction.replace () , 
Presenter 's were accumulated and everything went under the tail of the cat.
Googling smaltsa , was found method 
Fragment.isRemoving () , which seems to do the same thing, but for fragments. I rewrote 
PresenterManager's code and was pleased. The end…
Decision
... came my quiet life when I tried to make it work. Honestly, I tried this way and that, but the behavior of this method is fundamentally different from 
Activity.isFinishing () . Google was wrong. If you ever have a similar problem, think three times before using 
Fragment.isRemoving () . 
I'm serious . Especially pay attention to the logs when you rotate the screen.
By the way, with 
Acitivity.isFinishing (), too, everything is not so smooth: minimize the application with> 1 activation in the stack, wait for a situation of low memory, go back and use 
Up Navigation and * voila *! .. This was a simple recipe for fucking an 
Activity. isFinishing () == false to activate, which you will never see again.
UPD : As the 
bejibx user correctly noted, the remark about 
Activity.isFinishing () is not quite right. To understand why, it is better to read 
the comment thread .
Situation
A common task when implementing 
pagination is to display the 
ProgressBar while loading new data.
Unlike 
ListView , 
RecyclerView has much more potential - which is what 
RecyclerView.Adapter.notifyItemRangeInserted () is worth in comparison with 
the ListView headache .
However, having tried to use it in the project instead of the 
ListView , you immediately come across a lot of nuances: where is the 
ListView.setDivider () property? Where is something like 
ListView.addHeaderView () ? What else for 
RecyclerView.Adapter.getItemViewType () , etc., etc.
It is easy to understand that with all this dump of information, but something unpleasant still remains. Adding a 
Divider / Header makes writing code clouds. What to say about complex 
layout 'ah? It was possible to do 
RecheclerView with 4 different 
Header 's and 
Footer 's with controllers. Let's just say, sad and dejected, I walked for a very long time.
Decision
In fact, everything is not so bad if you know what to look for. The main problem 
RecyclerView (and its main advantage) is that you can do anything with it. There is practically no framework. Hence the problem: if you want 
Header , do it yourself. But fortunately, do it yourself, others have already done for us, so let's take advantage.
Typical problems and their solutions:
- Headings for groups of elements (for example, in the dictionary “A” will be the heading for all words beginning with this letter) - the easiest way to do this is through a single item-layout , without adding the 2nd unnecessary type ViewHolder 'a. Add a check that the current element marks the transition from one letter to another and turn on the header hidden in the layout via View.VISIBLE .
- Simple divider - copy-paste this code into the project. No extra fraud. Works through RecyclerView.addItemDecoration ()
- Add Header / Footer / Drag & Drop etc. - if you do handles, then either get a new type for each new ViewHolder (I do not advise), or do a WrapperAdapter (much nicer). But it is even better to look here and choose your favorite lib. Personally, I like two at once: FastAdapter and UltimateRecyclerView
- Need pagination , but too lazy to mess with Header / Footer for ProgressBar 's - Paginate library from one of the developers of twitter.
Although for me it still remains a mystery - why it was impossible to make some 
SimpleDivider / SimpleHeaderAdapter , etc. Immediately in the SDK?
What's wrong with him?
So much problem, how much lack of 
documentation . This is what it says:
If you want to see the data set. If the item is not located the same.
And here people are divided into two types. First: everything is clear. Second: Cho does that even mean that?
The problem is that even if you attributed yourself to the first people, you may be puzzled by the question: why this method? Yes, yes, to return a unique 
ID ! I know. But why is it necessary? And no, the answer is “Google writes that it will be scrolling faster!” Will not suit me.
But what's the matter
Acceleration from 
RecyclerView.Adapter.setHasStableIds () is really possible to get, but only in one case - if you everywhere use 
RecyclerView.Adapter.notifyDataSetChanged () (and here they deign to write why you need a stable id) . If you have static data, then this method will not give you anything, and maybe even slow down a bit due to internal 
ID checks. I found out about it only after reading the source code, and a bit later I stumbled upon 
this article .
Situation
The task is to get 
html text from the server and display it on the screen. The text is sent by the server as 
"& lt; html & gt;" . Everything. This is the whole task. Complicated? There is a 
WebView that can display 
html in a couple of lines. Why, even 
TextView can do it! Once or twice and ready ... yes? .. no? .. well, should it be ?!
Decision
Unfortunately, everything is not so smooth:
- Let's start with the fact that there is no method like HtmlUtils.unescape () in the Android SDK. If you want a "& lt;" turn it into "<" , then the easiest way (besides prescribing regex 'and handles) is to connect apache with its StringUtils.unescapeHtml4 () .
- The next problem will be artifacts when scrolling. All of a sudden (yes, the Android SDK?), The webview will flash in black. What to do - is told here and here . Personally, I was helped only by a combination of these approaches.
- And if you have not yet been surprised by the abundance of problems from such a simple task, then here is the point: you need to display the ProgressBar before the html page has been rendered. And then everything is bad. That is really bad. All solutions presented on stackoverflow work through time or do not work at all ( tyk , tyk ). The only hitherto working method was using WebView.setPictureListener () , however, it is now declared deprecated and there is nothing to be done about it.
 As a result, the only thing that can be advised is to refuse ProgressBar 'a. Or, if it’s really, really, really impatient, add it directly to the html code, checking the readiness of the page via javascript .But this is for the club elite mazahistov.
 
When / Where / Why?
(The situation is specific and does not apply directly to Android’s problems, but decided to add it as a seed before the next cuvette)
In response to one of the 
api- requests, a bit mask of access rights comes in the form of 
int 'a. It is necessary to process the elements of this mask.
The first thing that comes to mind is the 
int 'constants and bit operations for checks. Sure, it always works. But what if you want more? What about 
EnumSet ?
“No problem” - the bearded progger will answer and break the architecture of the models into several more levels: 
POJO, Model, Entity, UiModel and what else the devil is not joking. But if you want laziness and no extra. classes? What then?
Decision
We create the enum we need by taking care of the “bitness” of the names in 
@SerializedName :
enum accesspublic enum Access { @SerializedName("1") CREATE, @SerializedName("2") READ; @SerializedName("4") UPDATE; @SerializedName("8") DELETE; } 
 Define a 
JsonDeserializer to deserialize from 
json to 
EnumSet :
EnumMaskConverter public class EnumMaskConverter<E extends Enum<E>> implements JsonDeserializer<EnumSet<E>> { Class<E> enumClass; public EnumMaskConverter(Class<E> enumClass) { this.enumClass = enumClass; } @Override public EnumSet<E> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { long mask = json.getAsLong(); EnumSet<E> set = EnumSet.noneOf(enumClass); for (E bit : enumClass.getEnumConstants()) { final String value = EnumUtils.GetSerializedNameValue(bit); assert value != null; long key = Integer.valueOf(value); if ((mask & key) != 0) { set.add(bit); } } return set; } } 
 And add it to 
Gson :
Gsonbuilder GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter((new TypeToken<EnumSet<Access>>() {}).getType(), new EnumMaskConverter<>(Access.class)); Gson gson = gsonBuilder.create(); 
 As a result:
Using class MyModel { @SerializedName("mask") public EnumSet<Access> access; }  if (myModel.access.containsAll(EnumSet.of(Access.READ, Access.UPDATE, Access.DELETE))) {  } 
 7. Retrofit : Enum in @GET request
Situation
Let's start with the settings. 
Gson is formed as before. 
Retrofit is created like this:
new Retrofit.Builder () retrofit = new Retrofit.Builder() .baseUrl(ApiConstants.API_ENDPOINT) .client(httpClient) .addConverterFactory(GsonConverterFactory.create(gson)) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); 
 And the data looks like this:
enum season public enum Season { @SerializedName("3") AUTUMN, @SerializedName("1") SPRING; } 
 Thanks to the ability of 
Gson to directly parse the enum through the usual 
@SerializedName , it became possible to get rid of the need to create any additional classes-layers. All data will immediately go from requests to the 
Model . Everything is fine:
Retrofit Service public interface MonthApi { @GET("index.php?page[api]=selectors") Observable<MonthSelector> getPriorityMonthSelector(); @GET("index.php?page[api]=years") Observable<Month> getFirstMonth(@Query("season") Season season); } 
 Application class MonthSelector { @SerializedName("season") public Season season; }  MonthSelector selector = monthApi.getPriorityMonthSelector(); Season season = selector.season;  Month month = monthApi.getFirstMonth(season); 
 And now, dear experts, attention to the question! What went wrong and why is it not working?
Decision
I specifically omitted the information that it is not working here. The fact is that if you look in the logs, then the 
monthApi.getFirstMonth (season) query will be processed as 
index.php? Page [api] = years & season_lookup = AUTUMN ... "uh, what's the matter?" I will say. What is your answer? Why such a result? Haven't guessed yet? Then you are trapped.
When I ran into this task, it took me several hours of searching the source code to understand one thing (or rather even remember): yes, 
Gson is not used when sending 
@GET / 
@POST and other similar _queries_ in general! Indeed, when was the last time you saw something like 
index.php? Page [api] = years & season_lookup = {a: 123; b: 321} ? This makes no sense. 
Retrofit 2 uses 
Gson only when converting 
Body , but not for the requests themselves. Eventually? just used 
season.toString () - hence the result.
However, if you really want to sooo 
(and I am one of them) use 
enum with 
Gson conversion in the request, then 
here you are another converter, everything is as usual.
8. Retrofit : transfer auth-token
And finally, I would like to say one thing to those who write like this:
Any Retrofit Service public interface CoolApi { @GET("index.php?page[api]=need") Observable<Data> just(@Header("auth-token") String authToken);  
 Begin to use the 
Interceptor 'ora already! I understand that it is very simple to use 
Retrofit and therefore no one reads the documentation, but when you sit for 3 hours and clean the code not only from the 
auth-token , but also from any specific 
current_location, battery_level, busy_status - great 
sadness overtakes (do not ask why 
battery_level in each request. Himself in shock). You can read about it 
here .
Instead of conclusion
Well, this time there was a lot more text than I had planned. Some less interesting ditches had to be thrown out, while others I decided to leave for the next time.
Contrary to the 
promise of the previous part , this time I tried to make you not “google first”, but first of all think “why am I doing this?”. Sometimes the problem is not created by the SDK or the library, but by the programmer himself, and, unfortunately, in this case, everything is far more pitiable. Do not underestimate the chosen tool, as well as not overestimate it.
In general, if you like android and / or you plan to do it - always keep yourself up to date with 
world trends . Well, or look for a news resource more convenient for you. There you can find a lot of information about the 
Android SDK , 
popular libraries , etc., etc.