在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称(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 appDroidKaigi 2018 is a conference tailored for developers on 8th and 9th February 2018. Features
ContributingWe are always welcome your contribution! How to find the tasksWe 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 contributeIf 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 Development EnvironmentKotlinThis app is full Kotlin! RxJava2 & LiveDataConverting RxJava2's publisher to AAC LiveData with LiveDataReactiveStreams.
repository.sessions
.toResult(schedulerProvider)
.toLiveData()
fun <T> Publisher<T>.toLiveData() = LiveDataReactiveStreams.fromPublisher(this) GroupieBy 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
} ArchitectureThis app uses an Android Architecture Components(AAC) based architecture using AAC(LiveData, ViewModel, Room), Kotlin, RxJava, DataBinding, dependency injection, Firebase. Fragment -> ViewModelUse 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 -> RepositoryUse RxJava2(RxKotlin) and 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 -> DBUse Retrofit and save to the SessionDataRepository.kt override fun refreshSessions(): Completable {
return api.getSessions()
.doOnSuccess { response ->
sessionDatabase.save(response)
}
.subscribeOn(schedulerProvider.computation())
.toCompletable()
} DB -> RepositoryUse 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 -> ViewModelWe 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 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 -> FragmentFragment observe ViewModel's LiveData.
We can use the result with Kotlin 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()
}
}
}) ReleaseThe release process is automated by using gradle-play-publisher.
When we add 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 ProjectsSome contributors are challenging to develop iOS app with Kotlin/Native and Kotlin Multiplatform Projects. DroidKaigi 2018 Flutter AppThe unofficial conference app for DroidKaigi 2018 Tokyo https://github.com/konifar/droidkaigi2018-flutter ThanksThank you for contributing!
CreditThis project uses some modern Android libraries and source codes.
License
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论