Tuesday, December 28, 2021

Dealing with Depression in a Post Video Game Era

Wow that's a lot of words, what does it all mean?

I want to invite you for a moment to glimpse into my gamer life. Over the course of the last 2 months I have bought the following video games for myself. Numbers are loose estimates and not the actual price:


Ori and the Blind Forest ($15)

Ori and the Will of the Wisps ($15)

Baba is You ($10)

Deponia (4 games) ($2 each)

Lost in Random ($30)

GrindStone ($10)

Loop Hero ($20)

Yoku's Island Express ($10)

Figment ($3)

Moving Out ($7)

Darkest Dungeon ($20)

Tetris Effect: Connected ($40)

Mario Party Superstars ($60)

Nidhogg 2 ($6)

Castle Crashers ($10)

Risk of Rain 2 ($7) 

Chicory ($20)

Night in the Woods ($5)

Oxenfree ($2)


Some quick calculator math later, that's 22 games and $298 dollars spent. Not bad given that some of those games were on major sale. Of those games purchased, I've put about 70 hours into Tetris Effect, and have greatly enjoyed both Mario Party and Nidhogg.

All those other games though, I've played only a little. Most I've played only once for maybe an hour or two at most, like Baba is You, Deponia, Grindstone, Lost in Random, Loop Hero, Figment, or Darkest Dungeon.

There are actually 2 games (I'm not counting Castle Crashes or Risk of Rain having bought them just yesterday) on this list I've bought and just never ever played - both Ori games. They're great games (or so I've heard) and yet I've never even started them.

Now every gamer has a large backlog, and not getting around to games is not an unheard of thing. But let's examine this slightly more in depth.

Of these games listed above I've actually purchased multiple copies for other people (presents and such):

 

Tetris Effect Connected (4 more times)

Castle Crashers (2 more times)

Nidhogg 2 (1 more time)

Risk of Rain 2 (2 more times)

Moving Out (2 more times)

Figment (1 more time)

Mario Party (1 more time)

 

Which brings my total count up to 35 games and around $575 dollars spent on myself and others for strictly Nintendo Switch video games in the last two months. That's a lot of games.


Why buy so many?


If you want my self reflective diagnoses, its a way to deal with depression I suppose. The constant feeling of wanting something new - yet always being ultimately unsatisfied with what I have, even when I acquire the thing that I once thought would bring excitement into my barren gamer life. Now, it's not all bad, 70 hours in a Tetris video game is not exactly a waste of money. A fun time in a game like Mario Party or Nidhogg is something I wouldn't trade away for any amount of money - but what about all the rest of those games?

Did I really need to buy Baba is You only to just play it once and never touch it again? Did I need to buy Loop Hero even though I know I'm not usually a fan of roguelike or roguelite games? Why buy Risk of Rain if I know I'm not a fan of that style of game at all? Why spend 40 dollars on Tetris - furthermore, why spend 40 dollars on Tetris so many times for so many different people?

Did I really need to spend 300 dollars to purchase a PlayStation 4, and then buy PS Plus on an annual subscription for 70 dollars and Kingdom Hearts 3 for 60 dollars, only to not really enjoy the game? Why spend so much money, and take so much time, playing video games that I'm either not going to enjoy, or only enjoy briefly?

What I believe is that the cost is outweighed by the fun I would have playing the game with other people. This I believe is the one thing that helps me step away from the steep precipice of overwhelming depression, is knowing that, even if only for a brief moment, purchasing and playing a video game can help me and other people have fun - genuine good fun. It is unfortunate that it is so expensive, but such is the price of medication I suppose.


Code stuff later.


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
Check out my code on GitHub
=========================

Full Circle

I began my career as an Android developer by creating a power management application for old Android phones that would turn off Wifi and Data when the screen was off. This was back in the olden days, before AppCompat and support libraries - where we needed to use Eclipse to manually download JAR files and used ActionBarSherlock to support older devices because nobody actually had any modern version of Android.

Life has changed and wow - how we have grown.

I feel it is only fitting then that I come to you today, glad to announce that things have come full circle. I am now an Android developer 10 years older.

 

 

Developing a power management application for Android devices that saves battery when the screen turns off.

 

 

Built in two days as a simple pet project to do a simple task. Now hold on, before you complain about shitty power manager applications that don't actually do anything - this is not snake oil. There is no custom power managing logic happening here, since this application is very simple. It does exactly one thing.

When you turn the phone screen off, this application enables the Android system built-in power-saver mode. When you turn the screen back on, your phone is set back to normal mode. That's it.

By relying on the built in system power-saving mode, we can ensure that a bunch of things "actually work." Battery is actually saved because the system has the ability to shut off or throttle a bunch of things. Whitelists are correctly handed because this is just the same system-wide battery optimization whitelist that you already have on your phone. Nothing actually changes about your device, this application just helps to do one additional convenient thing for you.

As always, full open source with no tracking or analytics or advertisement. I hope to have it up on the store 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
Check out my code on GitHub
=========================

Saturday, December 4, 2021

Compose, ViewModels, and Configuration

Let's talk.

First is Jetpack Compose UI. It's cool, it's new. I've migrated all supported pyamsoft Android applications to use it. It comes with some new ways of doing things. This is largely a nerd corner post.

First, the move to Jetpack Compose UI sees the deprecation of a number of PYDroid things. The entire UiView system is deprecated, along with UiViewEvents and UiControllerEvents. The UiViewModel is deprecated. The only thing that survives the migration without deprecation is the UiViewState. Let me tell you why.

First, the UiViewEvent and UiControllerEvent and UiView existed as a hacky way to create a React-like render loop, where a ViewModel would control and constantly push an entire view state. In Compose UI, this is all done for us, so all of this ceremony around binding to the normal Android view system is gone. Write Composables as you normally would, pass then props and callbacks as you normally would, and have those callbacks call ViewModel methods as you normally would. This effectively migrates PYDroid-Arch from an MVI to a better MVVM architecture.

Second is ViewModels. I am going to put forward the controversial claim: You no longer need the Android Jetpack ViewModel. PYDroid uses completely independent simple ViewModels called ViewModelers instead of Jetpack ViewModel and it's weird ViewModelStore and other initialization quirks. Why do this? Well, lets examine what exactly we need from a ViewModel that we do not otherwise already have.

ViewModel comes with 2 very important things for us - it survives configuration changes, and with SavedStateHandle can also persist data across process death. As a trade off, we receive the ViewModel class which must be injected by a ViewModelStore and a Factory, and is difficult to configure with things like scope and injection. What if we could remove all this extra baggage, and be left with a ViewModel that still survives configuration changes and process persistence? What if we could manage scoping and injection simply through Dagger as we do for every other class in our project? Well lets see if Compose UI can't help us change things around.

Let's examine configuration changes first. What if I told you that Compose UI can handle all configuration changes on it's own due to the new system? Yes, thats right. You can finally add the configChanges line to your manifest as follows:

android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"

Also, be sure to override in your Fragments or Activities

override fun onConfigurationChanged(newConfig: Configuration) {
  super.onConfigurationChanged(newConfig)  
  mySyncDarkThemeFunction()
  myDialogSizingFunction()
  myComposeView.apply {
    if (isAttachedToWindow) {
      disposeComposition()
      createComposition()
    }
  }
}


This way your components will guarantee that Compose UI is kept in sync with the rest of the system like dark theme and dialog sizes and window sizes and whatnot.

This is massively important because now 1 of the two benefits of ViewModels has been effectively replaced. Now we just have to look as data persistence across process death, which can easily be achieved using our old friend onSaveInstanceState.

As you can see, we have all of the tools provided to us now to control the configChanges in our own application. No more die-recreate Activity lifecycle callbacks when a user simply rotates the phone, or opens the keyboard. Applications can be smooth and responsive, thanks to Compose UI.

Finally, let's talk about handling view state in a ViewModel. Many people like to use Kotlin data classes with val properties to represent their entire view state, and then calling copy() with individual fields changing to handle updates. This is, in fact, how PYDroid itself used to handle state internally. I'm writing today to recommend against this process, for reasons I'll detail now.

Compose runs a re-compose loop as often as it needs to keep things consistent. Let's say you've got a view like this psuedocode:

data class MyViewStateState(val name: String) : UiViewState

var myState = MyViewState(name = "")

fun onNameChanged(name: String) {
  myState = myState.copy(name = name)
}

@Composable
fun MyComposable(
  state: MyViewState,
  onNameChanged: (String) -> Unit,
) {
  val name = state.name
  TextField(
    value = name,
    onValueChange = onNameChanged,
  )
}



Each time you type a character into the TextField, it will re-compose. This will cause onNameChanged to be called which copies the myState object, allocating more memory, and then stores the variable. It's a ton of allocation and memory, which is slow, and bad.

Let's fix this, by replacing the data class State with an interface

interface MyViewState : UiViewState {
  val name: String
}

@ActivityScope
internal class MutableMyViewState @Inject internal constructor() : MyViewState {
  override var name by mutableStateOf("")
}
var myState = MutableMyViewState(name = "")

fun onNameChanged(name: String) {
  myState.name = name
}

Look at the differences in code now.

Notice how the Composable has not changed because we have correctly separated concerns of our View from our ViewModel, yay!

Now, whenever the name changes, the string will simply be assigned to an already allocated string in the MutableMyViewState, which is private to our ViewModel and to the Composable, MyViewState looks like it has not changed at all because it is now a simple interface. By doing ViewModel state this way we can avoid constantly re-allocating new objects whenever a recomposition happens.

These changes and more will be arriving in PYDroid 24.3.0, which deprecates basically anything touching the old Android View system and makes way for a Compose future.

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
Check out my code on GitHub
=========================