Details on Sofa's internals - dextorer/Sofa GitHub Wiki

Prologue

Sofa is the result of my hacky, hacky solution on having custom fragments working alongside Leanback components. I have written 4 articles on this subject, but ever since the first one came out, I knew how unstable and unreliable it was. This wrong feeling kept adding up until I decided it was time to tidy things up and find a nicer solution to this very problem.

Structure

This is a rough schematics of Sofa's structure.

com.sgottard.sofa  
  .support  
    |- BrowseSupportFragment  
    |- RowsSupportFragment  
    |- HeadersSupportFragment  
    |- BaseRowSupportFragment  
    |- BaseSupportFragment  
    |- BrandedSupportFragment  
  |- BrowseFragment  
  |- RowsFragment  
  |- HeadersFragment  
  |- BaseRowFragment  
  |- BaseFragment  
  |- BrandedFragment  
  |- ContentFragment  

As you can see, 6 Leanback classes (plus other 6 for the support version) had to be 'brutally' migrated to Sofa. However, 8 of them are untouched, and had to be imported only to avoid ugly hacks to access hidden components (such as Reflection). In particular:

  • BrowseFragment (and, in turn, BrowseSupportFragment) have been modified in several parts in order to allow custom content to be correctly loaded and handled
  • RowsFragment (and, in turn, RowsSupportFragment) now only implement the ContentFragment interface, which I introduced to generalize the concept of 'custom content'; in addition, all the implemented methods are basically NOPs

Considerations

Sofa is built with two concepts in mind:

  1. Reuse as many Leanback components as possible, without modifying them
  2. Allow any kind custom content, up to a certain level

I started analyzing the Leanback source code to see if there was any way of extending the existing components (by using Java's inheritance) in order to fulfil the aforementioned requirements. Unfortunately, due to final methods and package-local visibility, I realized that this was not the way to go.

For this reason, I had to manually migrate the Leanback classes to Sofa (I obviously moved those that were strictly needed). I am aware that this solution is not suitable for several different reasons, but I am open to suggestions ;)