Skip to content

Commit

Permalink
#259 Update readme and changelog
Browse files Browse the repository at this point in the history
  • Loading branch information
Zhuinden committed Mar 31, 2023
1 parent 7b46fa2 commit f6edbc6
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 59 deletions.
20 changes: 13 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,19 +183,25 @@ class FragmentStackHost(
backstack.addAheadOfTimeWillHandleBackChangedListener(willHandleBackChangedListener)
}

override fun onServiceRegistered() {
aheadOfTimeBackCallbackRegistry.registerAheadOfTimeBackCallback(backCallback)
}
override fun onServiceRegistered() {
aheadOfTimeBackCallbackRegistry.registerAheadOfTimeBackCallback(backCallback)
}

override fun onServiceUnregistered() {
aheadOfTimeBackCallbackRegistry.unregisterAheadOfTimeCallback(backCallback)
}
override fun onServiceUnregistered() {
aheadOfTimeBackCallbackRegistry.unregisterAheadOfTimeCallback(backCallback)
}
}
```

Meaning, whether back will be handled needs to be propagated up, and manage the enabled state of
Where `FragmentStackHost` gets the `AheadOfTimeBackCallbackRegistry`
from `serviceBinder.getAheadOfTimeBackCallbackRegistry()`.

So in this snippet, whether back will be handled needs to be propagated up, and manage the enabled state of
the `AheadOfTimeBackCallback` to intercept back if needed.

While this might seem a bit tricky, this is how Google does it in their own micromanagement of communicating with
the `onBackPressedDispatcher` as well, so evaluating ahead of time who will want to handle back later is unavoidable.

- DEPRECATED: `BackstackDelegate.onBackPressed()` and `Navigator.onBackPressed()`. Not only are they the same
as `backstack.goBack()` and merely managed to confuse people historically, but this deprecation mirros the deprecation
of `onBackPressed` in compileSdk 33, to push towards using predictive back.
Expand Down
119 changes: 68 additions & 51 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,50 +151,6 @@ class MainActivity : AppCompatActivity(), SimpleStateChanger.NavigationHandler {
}
```

*Note: Before supporting predictive back gestures and using `EVENT_BUBBLING` back handling model, the code that interops
with OnBackPressedDispatcher looked like this:*

``` kotlin
class MainActivity : AppCompatActivity(), SimpleStateChanger.NavigationHandler {
private lateinit var fragmentStateChanger: DefaultFragmentStateChanger

@Suppress("DEPRECATION")
private val backPressedCallback = object: OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
if (!Navigator.onBackPressed(this@MainActivity)) {
this.remove()
onBackPressed() // this is the reliable way to handle back for now
this@MainActivity.onBackPressedDispatcher.addCallback(this)
}
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

onBackPressedDispatcher.addCallback(backPressedCallback) // this is the reliable way to handle back for now

val binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)

fragmentStateChanger = DefaultFragmentStateChanger(supportFragmentManager, R.id.container)

Navigator.configure()
.setStateChanger(SimpleStateChanger(this))
.install(this, binding.container, History.single(HomeKey))
}

override fun onNavigationEvent(stateChange: StateChange) {
fragmentStateChanger.handleStateChange(stateChange)
}
}
```

Originally, handling back was simpler, as all you had to do is override `onBackPressed()` (then
call `backstack.goBack()`, if it returned `true` then you would not call `super.onBackPressed()`) , but in order to
support `BackHandler` in Compose, or Fragments that use `OnBackPressedDispatcher` internally, you cannot
override `onBackPressed` anymore in a reliable manner.

With targetSdkVersion 34 and with `android:enableOnBackInvokedCallback="true"` enabled, `onBackPressed` (
and `KEYCODE_BACK`) will no longer be called. In that case, the `AHEAD_OF_TIME` back handling model should be preferred.

Expand Down Expand Up @@ -351,24 +307,85 @@ override fun onNavigationEvent(stateChange: StateChange) { // using SimpleStateC
}
```

Whether you navigate forward or backward, or you rotate the screen, or you come back after low memory condition - it's irrelevant. The `StateChanger` will ***always*** handle the scenario in a predictable way.
Whether you navigate forward or backward, or you rotate the screen, or you come back after low memory condition - it's
irrelevant. The `StateChanger` will ***always*** handle the scenario in a predictable way.

## Dev Talk about Simple-Stack

## More information
For an overview of the "why" and the "what" of what Simple-Stack offers, you can check
out [this talk called `Simplified Single-Activity Apps using Simple-Stack`](https://www.youtube.com/watch?v=5ACcin1Z2HQ)
.

For more information, check the [wiki page](https://github.com/Zhuinden/simple-stack/wiki).
## Tutorial by Ryan Kay

## Talk
For a quick tutorial on how to set up dependency injection, model lifecycles, and reactive state management using
Simple-Stack, you can look at the tutorial by Ryan Michael Kay [**here, by clicking this
link**](https://youtu.be/yRVt6sALB-g?t=2600).)

For an overview of the "why" and the "what" of what Simple-Stack offers, you can check out [this talk called `Simplified Single-Activity Apps using Simple-Stack`](https://www.youtube.com/watch?v=5ACcin1Z2HQ).
## More information

For more information, check the [wiki page](https://github.com/Zhuinden/simple-stack/wiki).

## What about Jetpack Compose?

See https://github.com/Zhuinden/simple-stack-compose-integration/ for a default way to use composables as screens.

This however is only required if ONLY composables are used, and NO fragments. When using Fragments, refer to the official [Fragment Compose interop](https://developer.android.com/jetpack/compose/interop/interop-apis#compose-in-fragments) guide.
This however is only required if ONLY composables are used, and NO fragments. When using Fragments, refer to the
official [Fragment Compose interop](https://developer.android.com/jetpack/compose/interop/interop-apis#compose-in-fragments)
guide.

For Fragment + Simple-Stack + Compose integration, you can also
check [the corresponding sample](https://github.com/Zhuinden/simple-stack/tree/ced6d11e711fa2dda85e3bd7813cb2a192f10396/samples/advanced-samples/extensions-compose-example)
.

## About the event-bubbling back handling model

Note: Before supporting predictive back gestures and using `EVENT_BUBBLING` back handling model, the code that interops
with OnBackPressedDispatcher looks like this:

``` kotlin
class MainActivity : AppCompatActivity(), SimpleStateChanger.NavigationHandler {
private lateinit var fragmentStateChanger: DefaultFragmentStateChanger

@Suppress("DEPRECATION")
private val backPressedCallback = object: OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
if (!Navigator.onBackPressed(this@MainActivity)) {
this.remove()
onBackPressed() // this is the reliable way to handle back for now
this@MainActivity.onBackPressedDispatcher.addCallback(this)
}
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

onBackPressedDispatcher.addCallback(backPressedCallback) // this is the reliable way to handle back for now

val binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)

fragmentStateChanger = DefaultFragmentStateChanger(supportFragmentManager, R.id.container)

Navigator.configure()
.setStateChanger(SimpleStateChanger(this))
.install(this, binding.container, History.single(HomeKey))
}

override fun onNavigationEvent(stateChange: StateChange) {
fragmentStateChanger.handleStateChange(stateChange)
}
}
```

Originally, handling back was simpler, as all you had to do is override `onBackPressed()` (then
call `backstack.goBack()`, if it returned `true` then you would not call `super.onBackPressed()`) , but in order to
support `BackHandler` in Compose, or Fragments that use `OnBackPressedDispatcher` internally, you cannot
override `onBackPressed` anymore in a reliable manner.

For Fragment + Simple-Stack + Compose integration, you can also check [the corresponding sample](https://github.com/Zhuinden/simple-stack/tree/ced6d11e711fa2dda85e3bd7813cb2a192f10396/samples/advanced-samples/extensions-compose-example).
Now, either this should be used (if cannot migrate to `AHEAD_OF_TIME` back handling model), or migrate
to `AHEAD_OF_TIME` back handling model and `AheadOfTimeBackCallback`.

## License

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
public abstract class AheadOfTimeBackCallback {
private final long threadId = Thread.currentThread().getId();

private List<EnabledChangedListener> enabledChangedListeners = new ArrayList<>();
private final List<EnabledChangedListener> enabledChangedListeners = new ArrayList<>();

/**
* Allows registering for when a {@link AheadOfTimeBackCallback}'s enabled status has changed.
Expand Down

0 comments on commit f6edbc6

Please sign in to comment.