Name: conference-app-2018
Owner: DroidKaigi
Description: The Official Conference App for DroidKaigi 2018 Tokyo
Created: 2017-12-23 15:13:21.0
Updated: 2018-01-17 15:45:56.0
Pushed: 2018-01-17 22:15:19.0
Size: 3182
Language: Kotlin
GitHub Committers
User | Most Recent Commit | # Commits |
---|
Other Committers
User | Most Recent Commit | # Commits |
---|
DroidKaigi 2018 is a conference tailored for developers on 8th and 9th February 2018.
TBD
We are always welcome your contribution!
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!
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
).
This app is full Kotlin!
Converting RxJava2's publisher to AAC LiveData with LiveDataReactiveStreams.
AllSessionsViewModel.kt
sitory.sessions
.toResult(schedulerProvider)
.toLiveData()
LiveDataReactiveStreamsExt.kt
<T> Publisher<T>.toLiveData() = LiveDataReactiveStreams.fromPublisher(this)
By using Groupie you can simplify the implementation around RecyclerView.
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
This app uses an Android Architecture Components(AAC) based architecture using AAC(LiveData, ViewModel, Room), Kotlin, RxJava, DataBinding, dependency injection, Firebase.
Use LifecycleObserver
for telling lifecycle to ViewModel.
SessionsFragment.kt
s SessionsFragment : Fragment(), Injectable {
private lateinit var sessionsViewModel: SessionsViewModel
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
...
lifecycle.addObserver(sessionsViewModel)
...
SessionsViewModel.kt
s SessionsViewModel @Inject constructor(
private val repository: SessionRepository,
private val schedulerProvider: SchedulerProvider
ViewModel(), LifecycleObserver {
.
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
fun onCreate() {
...
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()
}
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()
}
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
s SessionDataRepository @Inject constructor(
private val sessionDatabase: SessionDatabase,
SessionRepository {
override val rooms: Flowable<List<Room>> =
sessionDatabase.getAllRoom().toRooms()
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
<T> Publisher<T>.toLiveData() = LiveDataReactiveStreams.fromPublisher(this) as LiveData<T>
And using Result
class for error handling with Kotlin extension.
<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())
}
otlin
ed 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)
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()
}
}
})
Some contributors are challenging to develop iOS app with Kotlin/Native and Kotlin Multiplatform Projects.
We are watching this project.
DroidKaigi2018iOS
Thank you for contributing!
This project uses some modern Android libraries and source codes.
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.