Git Product home page Git Product logo

conference-app-2019's Introduction

DroidKaigi 2019 official Android app

DroidKaigi 2019 is a conference tailored for developers on 7th and 8th February 2019.

You can download the binary built on master branch from Try it on your device via DeployGate

Features

top detail
image image
  • View conference schedule and details of each session
  • Set notification for upcoming sessions on your preference
  • Search sessions and speakers and topics
  • Show Information Feed

Contributing

We are always welcome your contribution!

How to find the tasks

We use GitHub issues to manage the tasks. Please find the issues you'd like to contribute in it. welcome contribute and easy are good for first contribution.

Of course, it would be great to send PullRequest which has no issue!

How to contribute

If you find the tasks you want to contribute, please comment in the issue like this to prevent to conflict contribution. We'll reply as soon as possible, but it's unnecessary to wait for our reaction. It's okay to start contribution and send PullRequest!

We've designated these issues as good candidates for easy contribution. You can always fork the repository and send a pull request (on a branch other than master).

Development Environment

Multi module project

We separate the modules for each feature.

image

You can check generated module dependency diagram

Unidirectional data flow(Flux-based) Architecture

Unidirectional data flow(Flux-based) Architecture with Kotlin Coroutines and AndroidX Libraries(LiveData, ViewModel, Room) DataBinding, Dagger and AssistedInject, Firebase etc.

Groupie

By using Groupie you can simplify the implementation around RecyclerView.

class SpeakerItem @AssistedInject constructor(
    @Assisted val speaker: Speaker, // Inject by AssistedInject
    val navController: NavController // Inject by Dagger
) : BindableItem<ItemSpeakerBinding>() {
    @AssistedInject.Factory
    interface Factory {
        fun create(
            speaker: Speaker
        ): SpeakerItem
    }

    override fun getLayout(): Int = R.layout.item_speaker

    override fun bind(itemBinding: ItemSpeakerBinding, position: Int) {
        itemBinding.speakerText.text = speaker.name
        ...
    }
}

We use AssistedInject for creating item.

    @Inject lateinit var speakerItemFactory: SpeakerItem.Factory
    
...
        val speakerItems = session
            .speakers
            .map { speakerItemFactory.create(it) }
        groupAdapter.update(speakerItems)

Architecture

Unidirectional data flow(Flux-based) Architecture with Kotlin Coroutines and AndroidX Libraries(LiveData, ViewModel, Room) DataBinding, dependency injection, Firebase etc.

Activity/Fragment -> Action Creator

image

Fragments just call Action Creator's method.

class SessionPagesFragment : DaggerFragment() {
    @Inject lateinit var announcementActionCreator: AnnouncementActionCreator
    override fun onActivityCreated(savedInstanceState: Bundle?) {
    ...
        announcementActionCreator.load()
    }

Action Creator <-> DB / API and Action Creator -> dispatcher

image

Action Creator fetches data from DB / API with Kotlin Coroutines suspend function. And Action Creator dispatches data loaded action and loading state changed actions.

class AnnouncementActionCreator @Inject constructor(
    override val dispatcher: Dispatcher,
    val firestore: Firestore,
    @PageScope val lifecycle: Lifecycle
) : CoroutineScope by lifecycle.coroutineScope,
    ErrorHandler {

    fun load() = launch {
        try {
            dispatcher.dispatch(Action.AnnouncementLoadingStateChanged(LoadingState.LOADING))
            // fetch announcement by Kotlin Coroutines suspend function
            dispatcher.dispatch(Action.AnnouncementLoaded(firestore.getAnnouncements()))
            dispatcher.dispatch(Action.AnnouncementLoadingStateChanged(LoadingState.LOADED))
        } catch (e: Exception) {
            onError(e)
            dispatcher.dispatch(Action.AnnouncementLoadingStateChanged(LoadingState.INITIALIZED))
        }
    }
}

Actions are just data holder class.

sealed class Action {
...
    class AnnouncementLoadingStateChanged(val loadingState: LoadingState) : Action()
    class AnnouncementLoaded(val announcements: List<Announcement>) : Action()
...
}

Dispatcher -> Store

image

Store subscribe dispatcher's action with Kotlin Coroutines channel and transform it to AndroidX LiveData. This store is a ViewModel. But if the store is used by the whole application(ex: UserStore), you can change the store to a singleton.

class AnnouncementStore @Inject constructor(
    dispatcher: Dispatcher
) : ViewModel() {
    val loadingState: LiveData<LoadingState> = dispatcher
        .subscribe<Action.AnnouncementLoadingStateChanged>()
        .map { it.loadingState }
        .toLiveData(LoadingState.LOADING)
    val announcements: LiveData<List<Announcement>> = dispatcher
        .subscribe<Action.AnnouncementLoaded>()
        .map { it.announcements }
        .toLiveData(listOf())
}

Store -> Activity/Fragment

image

In the fragment, we can observe Store's LiveData. You can display the UI with LiveData.

    override fun onActivityCreated(savedInstanceState: Bundle?) {
...
        announcementStore.loadingState.changed(viewLifecycleOwner) {
            // apply loading state for progress bar
            progressTimeLatch.loading = it == LoadingState.LOADING
        }
        announcementStore.announcements.changed(viewLifecycleOwner) { announcements ->
            // we can show UI with announcements
        }
...

Thanks

Thank you for contributing!

Credit

This project uses some modern Android libraries and source codes.

conference-app-2019's People

Contributors

a25max avatar bowyer-app avatar e10dokup avatar futabooo avatar jmatsu avatar kafumi avatar keithyokoma avatar kikuchy avatar konifar avatar kyoro avatar numeroanddev avatar ogapants avatar panpanini avatar rei-m avatar rmakiyama avatar ryu236 avatar satoshun avatar stvjbz avatar sys1yagi avatar takahirom avatar tarumzu avatar tomoya0x00 avatar tomoyashibata avatar ttanaka330 avatar wiroha avatar

Watchers

 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.