ispbox
08/12/2019, 6:46 PMclass ItemsUi(override val ctx: Context,
private val displayHelper: DisplayHelper) // Any other stuff for abstraction from platform...
: Ui {
/**
* Holder for buttons.
*/
val content = verticalLayout {
}
/**
* Root of Ui. Should be below all other properties for correct initialization order.
*/
override val root = verticalLayout {
background = resources.getDrawable(android.R.color.white, null)
add(content, lParams {
width = matchParent
height = matchParent
})
}
/**
* Creates UI based on data.
*/
fun createUi(items: List<Item>?) {
content.apply {
for (item in items) {
add(createButton(item), lParams {
width = matchParent
height = matchParent
})
}
}
}
}
class ItemsPresenter(ownerScope: CoroutineScope,
private var view: View?,
private val loadItemsCommand: LoadItemsCommand) : CoroutineScope by ownerScope {
interface View {
fun showItems(items: List<Item>?)
}
fun loadItems() = launch(<http://Dispatchers.IO|Dispatchers.IO>) {
val items = loadItemsCommand(null)
withContext(Dispatchers.Main) {
view?.showItems(items)
}
}
fun stop() {
view = null
}
}
class ItemsController : Controller(),
CoroutineScope,
KoinComponent,
ItemsPresenter.View {
private val itemsPresenter: ItemsPresenter by inject { parametersOf(this, this) }
private lateinit var itemsUi: ItemsUi
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup): View {
itemsPresenter.loadItems()
val displayHelper: DisplayHelper by inject()
itemsUi = ItemsUi(container.context, displayHelper, ::onItemSelection)
// or, alternatively, you can do something like that:
// itemsUi.button.onClick {
// val pushHandler = FadeChangeHandler(false)
// val popHandler = FadeChangeHandler()
//
// router.pushController(RouterTransaction.with(ItemDetailsController())
// .pushChangeHandler(pushHandler)
// .popChangeHandler(popHandler))
// }
return itemsUi.root
}
override fun onDestroyView(view: View) {
super.onDestroyView(view)
itemsPresenter.stop()
}
override fun showItems(items: List<Item>?) {
itemsUi.createUi(items)
}
private fun onItemSelection(itemId: Int) {
val pushHandler = FadeChangeHandler(false)
val popHandler = FadeChangeHandler()
router.pushController(RouterTransaction.with(ItemDetailsController())
.pushChangeHandler(pushHandler)
.popChangeHandler(popHandler))
}
override val coroutineContext: CoroutineContext by lazy {
(activity as MainActivity).coroutineContext
}
}
Controller
container. Don't use View.generateViewId()
, and just assign any int for it as described here (https://stackoverflow.com/questions/8460680/how-can-i-assign-an-id-to-a-view-programmatically). Id should be constant, otherwise you will get invalid backstack behavior on configuration changes.
BTW, is there any helper class for that is Splitties?private val rootId = 666001 // Constant root id.
private val buttonId = 666002 // Constant button id.
Do you retain view state this way, or save/restore it by exact variables in Ui subclasses?louiscad
08/13/2019, 7:46 PMR.id.not_existing_yet
.Button
is stateless and doesn't need it for example. Same for a TextView
. On the other hand, you definitely want stable ids for EditText
, ScrollView
, RecyclerView
, SeekBar
, SwitchCompat
, etc.ispbox
08/13/2019, 8:03 PMlouiscad
08/13/2019, 8:05 PMispbox
08/13/2019, 8:18 PMlouiscad
08/13/2019, 8:48 PMispbox
08/14/2019, 4:20 PMlouiscad
08/14/2019, 4:23 PM@Composable
function requires to be called from another one, much like suspend
functions. Regarding building part or all of the UI on a background thread, they are considering it and have to test if that has good outcomes in practice.ispbox
08/14/2019, 4:29 PMComposable
stuff.louiscad
08/14/2019, 4:40 PMsuspend
keyword is actually an annotation for the compiler, just like @Compose
is. They thought about making it a keyword (compose fun
), but they're not certain it's the right thing to add a keyword. An annotation is more library space and doesn't conflict with others in the project unless there's a fundamental clash.ispbox
08/14/2019, 4:43 PMCompose is looking for just letting us have conditionsAnd what's the problem now? 🙂 Kotlin already has this 'magic' 🙂
Compose is well into development for now, and I'll have to make a new UI for next release at work before it's done.You can use Flutter. I see no reason to be so excited with Compose... It doesn't serve coffee at least 🙂
louiscad
08/14/2019, 5:09 PMispbox
08/14/2019, 6:25 PMCompose is in Kotlin, that's why it'll work in Compose with nothing added from them.And the same applies to Splitties. Why are you so pessimistic? You already have a library, and Google has to work for maybe 1 or 2 years to get that in production.
louiscad
08/14/2019, 7:38 PMandroid.view.View
IMO. However, despite that, there's a need for a lot of fine tuning, and many things are very complicated. The current state makes me want to be a backend mobile developer only (not deal with how the app will actually look). Compose promises to make this dramatically easier, so I can only hope for it to come.ispbox
08/14/2019, 8:08 PMlouiscad
08/14/2019, 11:57 PMDialogFragment
without issues?ispbox
08/15/2019, 6:13 AMlouiscad
08/15/2019, 8:02 AM