• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

DroidKaigi/conference-app-2018: The Official Conference App for DroidKaigi 2018 ...

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称(OpenSource Name):

DroidKaigi/conference-app-2018

开源软件地址(OpenSource Url):

https://github.com/DroidKaigi/conference-app-2018

开源编程语言(OpenSource Language):

Kotlin 99.5%

开源软件介绍(OpenSource Introduction):

DroidKaigi 2018 official Android app

CircleCIWaffle.io - Columns and their card count

DroidKaigi 2018 is a conference tailored for developers on 8th and 9th February 2018.

Try it on your device via DeployGate

Features

  • 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 waffle.io 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 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

Kotlin

This app is full Kotlin!

RxJava2 & LiveData

Converting RxJava2's publisher to AAC LiveData with LiveDataReactiveStreams.

AllSessionsViewModel.kt

repository.sessions
    .toResult(schedulerProvider)
    .toLiveData()

LiveDataReactiveStreamsExt.kt

fun <T> Publisher<T>.toLiveData() = LiveDataReactiveStreams.fromPublisher(this)

Groupie

By using Groupie you can simplify the implementation around RecyclerView.

data class SpeakerItem(
        val speaker: Speaker
) : BindableItem<ItemSpeakerBinding>(speaker.id.hashCode().toLong()) {

    override fun bind(viewBinding: ItemSpeakerBinding, position: Int) {
        viewBinding.speaker = speaker
    }

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

Architecture

This app uses an Android Architecture Components(AAC) based architecture using AAC(LiveData, ViewModel, Room), Kotlin, RxJava, DataBinding, dependency injection, Firebase.

Fragment -> ViewModel

Use LifecycleObserver for telling lifecycle to ViewModel.

SessionsFragment.kt

class SessionsFragment : Fragment(), Injectable {

    private lateinit var sessionsViewModel: SessionsViewModel

...
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        ...
        lifecycle.addObserver(sessionsViewModel)
        ...

SessionsViewModel.kt

class SessionsViewModel @Inject constructor(
        private val repository: SessionRepository,
        private val schedulerProvider: SchedulerProvider
) : ViewModel(), LifecycleObserver {
  ...
    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    fun onCreate() {
    ...
}

ViewModel -> Repository

Use RxJava2(RxKotlin) and ViewModel#onCleared() for preventing leaking.

SessionsViewModel.kt

    private val compositeDisposable: CompositeDisposable = CompositeDisposable()

    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    fun onCreate() {
        repository
                .refreshSessions()
                .subscribeBy(onError = defaultErrorHandler())
                .addTo(compositeDisposable)
    }

    override fun onCleared() {
        super.onCleared()
        compositeDisposable.clear()
    }

Repository -> API, Repository -> DB

Use Retrofit and save to the Architecture Component Room.

SessionDataRepository.kt

    override fun refreshSessions(): Completable {
        return api.getSessions()
                .doOnSuccess { response ->
                    sessionDatabase.save(response)
                }
                .subscribeOn(schedulerProvider.computation())
                .toCompletable()
    }

DB -> Repository

Use Room with RxJava2 Flowable Support. And SessionDataRepository holds Flowable property.

SessionDao.kt

    @Query("SELECT room_id, room_name FROM session GROUP BY room_id ORDER BY room_id")
    abstract fun getAllRoom(): Flowable<List<RoomEntity>>

SessionDataRepository.kt

class SessionDataRepository @Inject constructor(
        private val sessionDatabase: SessionDatabase,
...
) : SessionRepository {

    override val rooms: Flowable<List<Room>> =
            sessionDatabase.getAllRoom().toRooms()

Repository -> ViewModel

We create LiveData from a ReactiveStreams publisher with LiveDataReactiveStreams

SessionsViewModel.kt

    val rooms: LiveData<Result<List<Room>>> by lazy {
        repository.rooms
                .toResult(schedulerProvider)
                .toLiveData()
    }

LiveDataReactiveStreamsExt.kt

fun <T> Publisher<T>.toLiveData() = LiveDataReactiveStreams.fromPublisher(this) as LiveData<T>

And using Result class for error handling with Kotlin extension.

fun <T> Flowable<T>.toResult(schedulerProvider: SchedulerProvider): Flowable<Result<T>> =
        compose { item ->
            item
                    .map { Result.success(it) }
                    .onErrorReturn { e -> Result.failure(e.message ?: "unknown", e) }
                    .observeOn(schedulerProvider.ui())
                    .startWith(Result.inProgress())
        }
sealed class Result<T>(val inProgress: Boolean) {
    class InProgress<T> : Result<T>(true)
    data class Success<T>(var data: T) : Result<T>(false)
    data class Failure<T>(val errorMessage: String?, val e: Throwable) : Result<T>(false)

ViewModel -> Fragment

Fragment observe ViewModel's LiveData. We can use the result with Kotlin when expression. In is Result.Success block, you can access data with result.data by Kotlin Smart cast.

SessionsFragment.kt

        sessionsViewModel.rooms.observe(this, { result ->
            when (result) {
                is Result.InProgress -> {
                    binding.progress.show()
                }
                is Result.Success -> {
                    binding.progress.hide()
                    sessionsViewPagerAdapter.setRooms(result.data)
                }
                is Result.Failure -> {
                    Timber.e(result.e)
                    binding.progress.hide()
                }
            }
        })

Release

The release process is automated by using gradle-play-publisher. When we add git tag, CI deploys the release apk to GooglePlay alpha. To know more details, see .circleci/config.yml

elif [[ "${CIRCLE_TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
    echo "Deploy to Google Play"
    openssl aes-256-cbc -k $PUBLISHER_KEYS_JSON_DECRYPT_PASSWORD -d -in encrypted-publisher-keys.json -out app/publisher-keys.json
    ./gradlew publishApkRelease
fi

iOS App with Kotlin/Native and Kotlin Multiplatform Projects

Some contributors are challenging to develop iOS app with Kotlin/Native and Kotlin Multiplatform Projects.
We are watching this project. DroidKaigi2018iOS

DroidKaigi 2018 Flutter App

The unofficial conference app for DroidKaigi 2018 Tokyo https://github.com/konifar/droidkaigi2018-flutter

Thanks

Thank you for contributing!

Credit

This project uses some modern Android libraries and source codes.

License

Copyright 2018 DroidKaigi

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.



鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
codeWithCal/KotlinCalculator发布时间:2022-07-10
下一篇:
pdichone/KotlinCourse发布时间:2022-07-10
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap