Friday, May 10, 2019

UI Architecture Design Patterns

At Google I/O 19, the Android Jetpack team announced Compose, which basically brings a React style UI toolkit to Android. Awesome.

For those who haven't worked in Javascript land before, I highly recommend you take a look at React and read about its philosophy behind the handling of state and data.

tldr; By enforcing a strict 1-1 relationship between a given component's state and the actual visuals drawn, you can be sure that data is always synchronized -- what ever business logic manipulates is what the screen will draw.

However, as with all nice things, Compose is not ready yet for prime time. In fact, it's not even ready for developer time - as it currently is in a pre-alpha stage. Google does recommend though that you prepare your applications for a world where a one way composable view state becomes the norm - and we don't have to wait at all to start doing that!

-----------------------------

Recently I was inspired by a talk given by Netflix engineers at a Droidcon event back in 2018 where they outlined how Netflix approached UI building via independent components which they composed into a screen. I adapted their architecture into the following couple of basic classes.

UiView.kt

@CheckResult
@IdRes
fun id(): Int

fun inflate(savedInstanceState: Bundle?)

fun saveState(outState: Bundle)

fun teardown()



UiViewModel.kt

fun bind(onRender: (state: T, oldState: T?) -> Unit)

fun unbind()



UiComponent.kt

@CheckResult
@IdRes
fun id(): Int

fun bind(
  owner: LifecycleOwner,
  savedInstanceState: Bundle?
  callback: C
)

fun saveState(outState: Bundle)





The UiComponent class would take any number of related UiViews and UiViewModels and would result in self-contained components that could be dropped into Android Views, Activities, or Fragments. Not bad - but there were many shortcomings with my implementation.

The application state was a two way flow, which would prove to be difficult to manage. Because a UiComponent was meant to be self contained, it was both a View and a Controller. My attempt at separating logic out of Activities and Fragments did not actually fix anything - it just changed the name of the problem to UiComponent. As a result, the relationship between UiView and UiViewModel was only loosely defined - sometimes the view would listen to the model and change how it displayed content on screen, sometimes the model would listen to the view and fire off navigation events using some rather hacky logic.

There also was the issue of creating the UiComponent class for each of these UI widget groupings - it was an extra file that really did not do much on its own except abstract other classes needlessly. It had to be better.

I went back to the drawing board and reasoned about how I could simplify this basic 3 class architecture I had built.

My first win was getting rid of the UiComponent class all together. It was basically a useless extra - it served as a Controller for the UiViews passed to it - but I had already established that in my Android architecture the Activity or Fragment was the controller. There was no need to have a Controller wrap another Controller, so UiComponent was removed.

UiView was a little bit trickier. Because Android's current view system is a far cry from reactive composable state, I had to make do with the current UI toolkit - which means I was required to have an inflate(Bundle?) method as that was the step where Android would inflate layout resources and find views and whatnot. Similarly, I needed to keep a teardown() method to release resources, as well as a saveState(Bundle) method for process death persistence. The id() method helped with laying out my UI widgets inside of ConstraintLayout containers, so it too stayed. Looks like I wasn't able to simplify UiView any amount - but that doesn't mean I was not able to improve it.

The main problem with UiView is that there was no established contract for when a UiView updates. Taking a page from the React toolkit, I added a render(T, T?) method which I would adopt as the only place to make dynamic UI updates in a UiView class.

Next I tackled the UiViewModel. My main issue with this class was that it required an arbitrary lifecycle of bind() and unbind() in order to make it possible to use at all. After working at it for a while, I managed to reduce UiViewModel to just one function, render() which will treat its lifecycle as the lifecycle of the RxJava stream it associates state events with. Meaning, once the RxJava stream opens, the ViewModel is "bound" and once the stream is disposed, the ViewModel is "unbound".

Instead of manually passing a callback to and from ViewModels and UiViews, I used an RxJava bus - one for the UiView as a stream of interaction events, and one for the ViewModel as a stream of presentation events. This way, a View would only emit events to its ViewModel, and the ViewModel would only emit events to the Controller. A uni-directional data flow at last.

Finally, to wrap up things and make my new spicy code play nicely with Android, I built a small stateless function which takes any number of UiViews and a ViewModel which controls them all and performs some boiler plate to set everything up. This createComponent function will inflate all Views, open the ViewModel state stream and UiView event stream, and register to a LifecycleObserver, which will dispose the stream and teardown the views when the lifecycle is destroyed. Much nicer.

I'm not the best speaker or the best writer - and can't really convey these ideas easily over a post. You may just be better off looking at the source code itself to gain a better understanding of what I'm trying to do. The buggy code for the new and hopefully improved UiViewModel can be found here. Here is the new UiView code, and my simple component wrapper.

I'll be updating all apps to follow this new architecture and eagerly await the day that Jetpack Compose releases. This new architecture should lead to fewer bugs for all the existing pyamsoft Android applications, as well as speed up the development process of my new application that is still a work in progress... but that's for another day.

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my Facebook Page

See my code on GitHub  
=========================

Tuesday, April 9, 2019

What's Up

Updates that's what.

Updates rolling out today/tomorrow for Home Button, ZapTorch, Pasterino, and WordWiz.

PYDroid has been updated to 19.2.X which is the first series to bring a new -arch module which provides an MVI design pattern for easy application building - it is powering all pyamsoft apps!

I'm working on something new at the moment - under wraps for now (unless you're able to read Git commits) since I need to make sure I have all the features rounded out as far as being feasible or not before I announce anything.

This release also marks the deprecation and unpublishing of PadLock off of the store. Unfortunately, like Power Manager before it - it is no longer welcome in a constantly changing Android environment. F for PadLock. F for Power Manager.

Long live pyamsoft.

More when I can, stay tuned...

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my FaceBook Page
Follow my Google+ Page
=========================

Wednesday, March 13, 2019

Long Time No Post

I feel like I've written this one before.

Time goes by and life catches up to us all, and I am no exception. I've been away from posting for a while, but have not been away from development. In fact, I've been working for the past couple of months re-architecting all of the pyamsoft applications to use a fancy new View-Ui-Component architecture that was introduced by Netflix at a Droidcon in 2018. It's been a wild ride and has opened up new ways for me to think and design applications.

Speaking of the applications, I've spent the last few months working on PadLock, and was hoping to release an update once I was satisfied with the codebase. However, with the recent Android Q beta announced, I find myself halted in my tracks by the big G themselves.

Android Q will be fantastic I'm sure, but it brings a change that is fundamentally incompatible with how PadLock operates. This change in how Activities can be launched from the background is the death knoll for PadLock and possibly many other applications. While I avoided the SMS fiasco, no man is safe forever.

As such, I am ceasing PadLock development. Sadly, while I am sure I could use a system level OVERLAY_WINDOW to get around the current background requirements, I am sure a future day will come where that is deprecated too in favor of PiP mode, or some official overlay API. Neither would work for PadLock's case - as its job is to be a full screen locker and directly intrude on the usage cycle of a nefarious user. With Android's continued lock down on the ability for applications to do unique and complex things across the device, PadLock is no longer a welcome application in the new world ecosystem.

I will still release updates for the other applications, but please note that once you upgrade your device to the shiny new Android Q later this year PadLock will cease to work at all. It saddens me to admit this, but it was fun while it lasted. I hope many of you found use of the tool I created.

Stay tuned.

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my FaceBook Page
Follow my Google+ Page
=========================

Tuesday, November 13, 2018

I am the night

Dark mode.

I like it, as a developer.

You like it as an insomniac who can't just seem to stop looking at Instagram and Reddit when its 2 AM and the room is already dark and you should have been asleep an hour ago because you've got an early day tomorrow.

It saves battery life.
It's cool to dynamically switch themes and see the app re-color itself correctly.


It's in - supported by all pyamsoft Android applications on the next release.


See you there!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my FaceBook Page
Follow my Google+ Page
=========================

Tuesday, October 9, 2018

Updates

Tiny update was released which should fix crashes for folks on older KitKat devices, as well as people who have a very specific PadLock setup.

It'll trickle in in a couple of hours. Try it out.

Stay tuned for hopefully new stuff.

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my FaceBook Page
Follow my Google+ Page
=========================

Tuesday, September 11, 2018

PadLock and battery life

Battery life is probably the single most important resource on a modern mobile device. The amount of battery left can directly and indirectly determine how long a user can continue using a device, how frequently they interact with the device, and even how fast and power hungry the device operates.

PadLock is an aggressive screen locker that tries to do its best to secure sensitive information on the device while still staying out of the way when not needed. It is this hands off operating style that has given PadLock the one thousand users it has today - and I'm very grateful for that - the opportunity it has given me to reach a wide audience and develop useful tools for all of you has been second to none.

PadLock is unfortunately a little more power hungry as a result of this aggressive operating. If it is enabled - which it must be to be useful - PadLock runs 24/7 365 days a year protecting your device. Because of this, PadLock uses a lot of energy and can sometimes keep the device awake when it should be sleeping.

The next update to PadLock will introduce some changes to hopefully rectify these overstepping of device resource usage.

PadLock will not actively look for new applications when the screen is off. This will save battery while the screen is off (which for many devices is most of the time) and will instantly be back online to lock new applications once the screen turns on.

PadLock does not need to be run all the time. When you need additional security for your device, PadLock is extremely useful - but when it is just you and your phone or tablet lying down in bed relaxing, PadLock does not need to be there locking new applications. The next update will bring the ability to pause PadLock - either until you manually re-enable it or for a temporary period after which it will resume itself. This will save battery in situations where PadLock is not needed because you are interacting with your device in a safe and trusted environment.

PadLock is not the only application on your device, and its time it started acting like it. This next version of PadLock will bring many exciting new changes!

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my FaceBook Page
Follow my Google+ Page
=========================

Wednesday, August 29, 2018

Better Locking

So PadLock is powered by this thing called Usage Access which is one of the very few (possibly one of two) things in Android that is allowed to watch the phone as a whole instead of just itself as a specific application.

Using its special Usage Access powers, PadLock is able to see the last used app on the phone, compare it to its list of "I want these apps locked" and lock the app if it is needed.

Unfortunately, these special powers are very dumb and difficult to work with resulting in PadLock sometimes being overly aggressive in watching for the last used app on the phone. PadLock was so aggressive it would even watch while the screen was off - which is an oversight on my end. If the screen is off - after all - the device is not being used and therefore would not need to detect the last used application for locking.

So the next version of PadLock will come with an optimization which basically puts it to sleep while the device screen is off. This will save a large amount of battery - since most of the time the device is off in a pocket or a bag - and will let PadLock be a better Android citizen.

I'm excited to release this change along with many stability and memory improvements in the next release cycle.

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my FaceBook Page
Follow my Google+ Page
=========================

Sunday, August 5, 2018

Updatesssss

Pushed out some Android updates today.

Most notable includes PadLock 3.0.0 which gets a fresh coat of paint as well as a more reliable backend storage solution! Check it out on the store here and leave me some feedback!

I've noticed some issues with Android P which I will be addressing shortly but decided to release anyway because let's be honest who is using Android P when its still in developer preview.

Updates to everything for better or for worse. Report bugs to me via the bug report dialog in app! Thanks for sticking with me through the last couple months of radio silence, and I hope to continue making new interesting creations for all of you.

Stay tuned!

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my FaceBook Page
Follow my Google+ Page
=========================

Saturday, July 28, 2018

Long Time No Nothing

Hey remember me?

I'm still here.

Haven't released anything new for a while - life catches up to us all in weird ways and I've found myself busy with other things that means I don't have endless hours to just update Android apps.

Lame I know.

I have some changes I want to get out but things need to stabilize around libraries and the new AndroidX changes with the new Android P stuff, so its all pretty up in the air at the moment.

I don't want to push out builds using Alpha libraries - but I'll settle for "production ready" beta libraries I suppose.

New stuff coming when I have the time - hopefully I have the time soon.


Stay tuned.

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my FaceBook Page
Follow my Google+ Page
=========================

Wednesday, April 4, 2018

Crashtacular

I have recently removed Firebase Crash Reporting from all pyamsoft Android applications. The crash reporting on the Play Store has greatly improved in the past year or so, and I find that I no longer need the specific real time crash reporting of the Firebase toolkit. The recent GDPR changes also serve to encourage me to remove the otherwise unused library from the Android applications I publish.

Aside from this, I have also updated git-ssh and ipwaiter - both which are written in Python now, and have cleaned up the Android projects to play nicer with Android Oreo now that I have a device running the latest version of Android again (thanks Lineage OS)!

Stay tuned.

========================
Follow pyamsoft around the Web for updates and announcements about the newest applications!
Like what I do?

Send me an email at: pyam.soft@gmail.com
Or find me online at: https://pyamsoft.blogspot.com

Follow my FaceBook Page
Follow my Google+ Page
=========================