Giter VIP home page Giter VIP logo

conference-app-2021's Introduction

DroidKaigi Logo DroidKaigi 2021 official app

Guides

Development

Features

Now this app has the Feed feature. We will deliver Feed and events related to DroidKaigi.

Home Drawer

Design

https://www.figma.com/file/IFlrbfmBSdYvUz7VmSzfLV/DroidKaigi_2021_official_app

Try it out

The builds being distributed through mobile app distribution services.

  • Production (TBR)
  • Try the latest staging through Download to device
  • and more... (tbw)

Contributing

We always welcome any and all contributions! See CONTRIBUTING.md for more information

For Japanese speakers, please see CONTRIBUTING.ja.md

Requirements

Latest Android Studio Arctic Fox and higher. You can download it from this page.
Xcode version is 12.4 (If you do iOS development)

Tech Stacks

Kotlin Multiplatform

TBD

Jetpack Compose

Modern Development

  • Jetpack Compose
  • Kotlin Coroutines & Flows
  • Dagger Hilt
  • DataStore
  • Kotlin Multiplatform

Architecture

Unidirectional data flow

Compose processing and ViewModel processing are performed by Unidirectional data flow.

Compose unidirectional data flow

By performing State hoisting(pass the value and receive the event), Jetpack Compose displays with unidirectional data flow.

/**
 * stateful
 */
@Composable
fun FeedScreen(
    onNavigationIconClick: () -> Unit,
    onDetailClick: (Feed) -> Unit,
) {
...

    val (
        state,
        effectFlow,
        dispatch,
    ) = use(feedViewModel())

    val context = LocalContext.current
    effectFlow.collectInLaunchedEffect { effect ->
        when (effect) {
            is FeedViewModel.Effect.ErrorMessage -> {
                scaffoldState.snackbarHostState.showSnackbar(
                    effect.appError.getReadableMessage(context)
                )
            }
        }
    }

    FeedScreen(
        // ...
        FeedContents = state.filteredFeedContents,
        onFavoriteChange = {
            dispatch(FeedViewModel.Event.ToggleFavorite(Feed = it))
        },
        // ...
    )
}

/**
 * stateless
 */
@Composable
private fun FeedScreen(
    // ...
    FeedContents: FeedContents,
    onFavoriteChange: (Feed) -> Unit,
    // ...
) {
    Column {
        BackdropScaffold(
            backLayerBackgroundColor = MaterialTheme.colors.primarySurface,
            scaffoldState = scaffoldState,
            backLayerContent = {
                BackLayerContent(filters, onFavoriteFilterChanged)
            }
// ...
        )
// ...
    }
}

ViewModel unidirectional data flow

This app handles the ViewModel with an MVI-like interface.

Compose

    val (
        state,
        effectFlow,
        dispatch,
    ) = use(feedViewModel())

    val context = LocalContext.current
    effectFlow.collectInLaunchedEffect { effect ->
        when (effect) {
            is FeedViewModel.Effect.ErrorMessage -> {
                scaffoldState.snackbarHostState.showSnackbar(
                    effect.appError.getReadableMessage(context)
                )
            }
        }
    }

    FeedScreen(
        // ...
        FeedContents = state.filteredFeedContents,
        onFavoriteChange = {
            dispatch(FeedViewModel.Event.ToggleFavorite(Feed = it))
        },
        // ...

This state, effectFlow and dispatch are created from ViewModel.

state represents the state that the UI should display.

effectFlow represents a one-time event such as a Snackbar display.

And dispatch represents a change of state.

ViewModel Interface

interface UnidirectionalViewModel<EVENT, EFFECT, STATE> {
    val state: StateFlow<STATE>
    val effect: Flow<EFFECT>
    fun event(event: EVENT)
}

use(viewModel) function

@Composable
inline fun <reified STATE, EFFECT, EVENT> use(
    viewModel: UnidirectionalViewModel<EVENT, EFFECT, STATE>,
):
    StateEffectDispatch<STATE, EFFECT, EVENT> {
    val state by viewModel.state.collectAsState()

    val dispatch: (EVENT) -> Unit = { event ->
        viewModel.event(event)
    }
    return StateEffectDispatch(
        state = state,
        effectFlow = viewModel.effect,
        dispatch = dispatch
    )
}

Testable & Previewable & Faster debug

Jetpack Compose is still a new technology. We are thinking of best practices. We will try to improve testing, preview and build by using Fake. For example, this app allows you to interact with the Android Studio Preview as if it were a real app.

preview

This is possible by creating a Fake ViewModel and making it reliable.

How to make Fake's ViewModel reliable

Do the same test for Fake and the real thing by testing against the interface. This makes Fake's ViewModel reliable. This technique of doing the same test against Fake was introduced in "Build testable apps for Android" session(Google I/O'19).

You can also prevent forgetting to update by forcing the implementation with interface and . Also, by forcing the implementation with interface and " Exhaustive ", it is possible to prevent forgetting to update Fake's ViewModel.

override fun event(event: FeedViewModel.Event) {
    coroutineScope.launch {
        @Exhaustive
        when (event) {
            is FeedViewModel.Event.ChangeFavoriteFilter -> {

How to make it previewable and testable

This app uses fake's ViewModel to enable preview.

@Preview(showBackground = true)
@Composable
fun FeedScreenPreview() {
    Conferenceapp2021FeedTheme(false) {
        ProvideFeedViewModel(viewModel = fakeFeedViewModel()) {
            FeedScreen {
            }
        }
    }
}

How to debug fast?

If you want to check the UI display, you can check it in the Preview of Android Studio. In that case, the required task is :uicomponent-compose:main:compileDebugKotlin. Therefore, there is no need to build the data module that contains the definitions such as API and the build of Android dex, so you can quickly build and check. Also, changes to the data layer do not affect the ui module, so you can build faster.

Overall architecture

Thanks

Thank you for contributing!

Contributors

GitHub : Contributors

Designer

nontan

Trouble Shooting

Android Gradle plugin requires Java 11 to run. You are currently using Java 1.X

JDK 1.8 is a requirement to build an Android project basically, but AGP 7.0 requires JDK 11. Please make sure you are using Java 11. Please note that the java version of Gradle Daemon is determined at the launch-time, so ./gradlew --stop might be required for you.

The option 'android.enableBuildCache' is deprecated.

android.enableBuildCache is REMOVED in AGP 7.0. android.enableBuildCache=false has no issue but builds randomly succeed with true value. This may affect to those who declare android.enableBuildCache=true in their $GRADLE_USER_HOME/gradle.properties.

conference-app-2021's People

Contributors

takahirom avatar jmatsu avatar watanavex avatar tick-taku avatar tomoya0x00 avatar fornewid avatar atsuya046 avatar dai1678 avatar ryunen344 avatar sobaya-0141 avatar tfandkusu avatar ntsk avatar akihiro-n avatar ki-0302 avatar kafumi avatar mhidaka avatar pluu avatar mightyfrog avatar ked4ma avatar a25max avatar koutamatsushita avatar index197511 avatar numeroanddev avatar mkano9 avatar kmachida12345 avatar anandwana001 avatar yuheikawakami avatar mattukouta avatar kumamotone avatar nanaten avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.