From b74e54ccefac7561592df31a341be51d608ed4a1 Mon Sep 17 00:00:00 2001 From: Salvatore Ranieri Date: Thu, 9 May 2019 13:03:03 +0200 Subject: [PATCH 01/10] first implementation of channel (To be updated) --- app/build.gradle | 5 + .../ktandroidarchitecture/ui/LoginActivity.kt | 28 +++++- .../kt/ktandroidarchitecture/ui/Note.kt | 18 ++++ .../ktandroidarchitecture/ui/NoteChannel.kt | 5 + .../ui/NoteDataSource.kt | 5 + .../ui/PagedListAdapterImpl.kt | 37 ++++++++ .../usecase/LoginUseCase.kt | 1 - .../viewmodel/LoginViewModel.kt | 11 +++ app/src/main/res/layout/activity_login.xml | 10 +- app/src/main/res/layout/note_list_item.xml | 15 +++ ktandroidarchitecturecore/build.gradle | 1 + .../interactor/BasePositionalDatasource.kt | 59 ++++++++++++ .../interactor/Channel.kt | 94 +++++++++++++++++++ .../interactor/PositionalChannel.kt | 85 +++++++++++++++++ 14 files changed, 368 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/Note.kt create mode 100644 app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/NoteChannel.kt create mode 100644 app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/NoteDataSource.kt create mode 100644 app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/PagedListAdapterImpl.kt create mode 100644 app/src/main/res/layout/note_list_item.xml create mode 100644 ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BasePositionalDatasource.kt create mode 100644 ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/Channel.kt create mode 100644 ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/PositionalChannel.kt diff --git a/app/build.gradle b/app/build.gradle index 3747c28..0c43e39 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -27,6 +27,7 @@ android { dependencies { def ktx_version = "2.0.0" + def kotlin_coroutines_version = "1.0.1" implementation fileTree(dir: 'libs', include: ['*.jar']) implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" @@ -41,5 +42,9 @@ dependencies { testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test:runner:1.1.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0' + + implementation 'androidx.paging:paging-runtime-ktx:2.1.0' + + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version" } diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt index 30f20c4..275ab77 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt @@ -1,17 +1,18 @@ package com.sysdata.kt.ktandroidarchitecture.ui -import android.app.Activity -import androidx.lifecycle.ViewModelProvider -import androidx.lifecycle.ViewModelProviders import android.os.Bundle + import android.text.Editable import android.text.TextWatcher import android.view.View +import android.widget.LinearLayout import android.widget.Toast import androidx.fragment.app.FragmentActivity +import androidx.lifecycle.ViewModelProviders +import androidx.paging.PagedList +import androidx.recyclerview.widget.LinearLayoutManager import com.sysdata.kt.ktandroidarchitecture.R import com.sysdata.kt.ktandroidarchitecture.repository.model.UIUserLogged -import com.sysdata.kt.ktandroidarchitecture.repository.model.UserLogged import com.sysdata.kt.ktandroidarchitecture.usecase.LoginActionParams import com.sysdata.kt.ktandroidarchitecture.viewmodel.LoginViewModel import it.sysdata.ktandroidarchitecturecore.exception.Failure @@ -20,6 +21,7 @@ import kotlinx.android.synthetic.main.activity_login.* class LoginActivity : FragmentActivity(), View.OnClickListener, TextWatcher { private var viewModel : LoginViewModel? = null + private var adapter: PagedListAdapterImpl? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -37,6 +39,24 @@ class LoginActivity : FragmentActivity(), View.OnClickListener, TextWatcher { viewModel?.actionLogin?.observe(this, ::onUserLoggged) viewModel?.actionLogin?.observeFailure(this, ::onLoginFailed) + + + viewModel?.channelNotes?.initDatasource(listOf(Note(), Note(), Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note())) + + adapter = PagedListAdapterImpl { + Toast.makeText(this, "note : $it", Toast.LENGTH_SHORT).show() + } + + recycler_view.layoutManager = LinearLayoutManager(this, LinearLayout.VERTICAL, false) + recycler_view.adapter = adapter + + viewModel?.channelNotes?.observe(this,::onPostNote) + } + + private fun onPostNote(list: PagedList?) { + list?.let { + adapter?.submitList(list) + } } private fun onLoginFailed(failure: Failure?) { diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/Note.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/Note.kt new file mode 100644 index 0000000..1f9a514 --- /dev/null +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/Note.kt @@ -0,0 +1,18 @@ +package com.sysdata.kt.ktandroidarchitecture.ui + +import androidx.recyclerview.widget.DiffUtil +import java.util.* + +data class Note(val noteId: String = UUID.randomUUID().toString()) { + companion object { + val DiffCallback = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: Note, newItem: Note): Boolean + = oldItem.noteId == newItem.noteId + + override fun areContentsTheSame(oldItem: Note, newItem: Note): Boolean + = oldItem.noteId == newItem.noteId && oldItem.title == newItem.title && oldItem.content == newItem.content + } + } + var title: String = "" + var content: String = "" +} \ No newline at end of file diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/NoteChannel.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/NoteChannel.kt new file mode 100644 index 0000000..626e1a2 --- /dev/null +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/NoteChannel.kt @@ -0,0 +1,5 @@ +package com.sysdata.kt.ktandroidarchitecture.ui + +import it.sysdata.ktandroidarchitecturecore.interactor.PositionalChannel + +class NoteChannel:PositionalChannel() \ No newline at end of file diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/NoteDataSource.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/NoteDataSource.kt new file mode 100644 index 0000000..cbbbe90 --- /dev/null +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/NoteDataSource.kt @@ -0,0 +1,5 @@ +package com.sysdata.kt.ktandroidarchitecture.ui + +import it.sysdata.ktandroidarchitecturecore.interactor.BasePositionalDatasource + +class NoteDataSource: BasePositionalDatasource() \ No newline at end of file diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/PagedListAdapterImpl.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/PagedListAdapterImpl.kt new file mode 100644 index 0000000..f80f677 --- /dev/null +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/PagedListAdapterImpl.kt @@ -0,0 +1,37 @@ +package com.sysdata.kt.ktandroidarchitecture.ui + +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.paging.PagedListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.sysdata.kt.ktandroidarchitecture.R + +class PagedListAdapterImpl(val onClick: (Note) -> Unit) : PagedListAdapter(Note.DiffCallback) { + class ListItemViewHolder(val view: View): RecyclerView.ViewHolder(view) { + var note: Note? = null + set(value) { + if(value != null){ + val tv: TextView = view.findViewById(R.id.itemText) + tv.text = value.toString() + } + field = value + } + } + + companion object { + private val TAG = this::class.java.simpleName + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListItemViewHolder + = ListItemViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.note_list_item, parent, false)) + + override fun onBindViewHolder(holder: ListItemViewHolder, position: Int) { + Log.d(TAG, "Binding view holder at position $position") + holder.note = getItem(position) + holder.view.setOnClickListener { onClick(holder.note!!) } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/usecase/LoginUseCase.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/usecase/LoginUseCase.kt index 6752a8a..bda8315 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/usecase/LoginUseCase.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/usecase/LoginUseCase.kt @@ -5,7 +5,6 @@ import com.sysdata.kt.ktandroidarchitecture.repository.model.UserLogged import it.sysdata.ktandroidarchitecturecore.exception.Failure import it.sysdata.ktandroidarchitecturecore.functional.Either import it.sysdata.ktandroidarchitecturecore.interactor.UseCase -import kotlinx.coroutines.experimental.delay class LoginUseCase: UseCase() { override suspend fun run(params: LoginActionParams): Either { diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/viewmodel/LoginViewModel.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/viewmodel/LoginViewModel.kt index fb17b41..0c5bce5 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/viewmodel/LoginViewModel.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/viewmodel/LoginViewModel.kt @@ -2,9 +2,15 @@ package com.sysdata.kt.ktandroidarchitecture.viewmodel import com.sysdata.kt.ktandroidarchitecture.repository.model.UIUserLogged import com.sysdata.kt.ktandroidarchitecture.repository.model.UserLogged +import com.sysdata.kt.ktandroidarchitecture.ui.Note +import com.sysdata.kt.ktandroidarchitecture.ui.NoteChannel +import com.sysdata.kt.ktandroidarchitecture.ui.NoteDataSource import com.sysdata.kt.ktandroidarchitecture.usecase.LoginActionParams import com.sysdata.kt.ktandroidarchitecture.usecase.LoginUseCase import it.sysdata.ktandroidarchitecturecore.interactor.Action +import it.sysdata.ktandroidarchitecturecore.interactor.BasePositionalDatasource +import it.sysdata.ktandroidarchitecturecore.interactor.Channel +import it.sysdata.ktandroidarchitecturecore.interactor.PositionalChannel import it.sysdata.ktandroidarchitecturecore.platform.BaseViewModel class LoginViewModel: BaseViewModel() { @@ -12,4 +18,9 @@ class LoginViewModel: BaseViewModel() { val actionLogin = Action.Builder() .useCase(LoginUseCase::class.java) .buildWithUiModel { UIUserLogged(it.username) } + + val channelNotes = Channel.Builder() + .channel(NoteChannel::class.java) + .dataSource(NoteDataSource::class.java) + .buildWithUiModel() } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 2cf593e..b694922 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -1,6 +1,8 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/note_list_item.xml b/app/src/main/res/layout/note_list_item.xml new file mode 100644 index 0000000..7be0169 --- /dev/null +++ b/app/src/main/res/layout/note_list_item.xml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/ktandroidarchitecturecore/build.gradle b/ktandroidarchitecturecore/build.gradle index 717081e..8666120 100644 --- a/ktandroidarchitecturecore/build.gradle +++ b/ktandroidarchitecturecore/build.gradle @@ -64,6 +64,7 @@ dependencies { implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'androidx.paging:paging-runtime-ktx:2.1.0' } repositories { diff --git a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BasePositionalDatasource.kt b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BasePositionalDatasource.kt new file mode 100644 index 0000000..a183506 --- /dev/null +++ b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BasePositionalDatasource.kt @@ -0,0 +1,59 @@ +package it.sysdata.ktandroidarchitecturecore.interactor + +import androidx.paging.PositionalDataSource + + +open class BasePositionalDatasource: PositionalDataSource(){ + + private var defaultLoadSize: Int? = null + private lateinit var datas: List + private var currentPosition: Int = 0 + + fun initDataSource(datas: List, defaultLoadSize: Int? = null){ + this.datas = datas + this.defaultLoadSize = defaultLoadSize + } + + override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback) { + val loadSize = params.loadSize + val startPosition = params.startPosition + + val subList = if(currentPosition > 0 && defaultLoadSize != null){ + getSubList(currentPosition, defaultLoadSize as Int) + } else{ + getSubList(startPosition, loadSize) + } + + callback.onResult(subList) + } + + override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback) { + var startPosition = params.requestedStartPosition + var pageSize = params.pageSize + val placeholdersEnabled = params.placeholdersEnabled + val requestedLoadSize = params.requestedLoadSize + + startPosition = if(startPosition < datas.size) startPosition else 0 + + defaultLoadSize?.let { + if(pageSize > it){ + pageSize = it + } + } + val subList = getSubList(startPosition, requestedLoadSize) + if(placeholdersEnabled){ + callback.onResult(subList, startPosition, requestedLoadSize) + } else { + callback.onResult(subList, startPosition) + } + } + + private fun getSubList(startPosition: Int, defaultLoadSize: Int): List { + if(startPosition >= datas.size){ + return datas.subList(datas.size - 1, datas.size - 1) + } + val endIndex = if (startPosition + defaultLoadSize <= datas.size) startPosition + defaultLoadSize else datas.size - 1 + currentPosition = endIndex + return datas.subList(startPosition, endIndex) + } +} \ No newline at end of file diff --git a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/Channel.kt b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/Channel.kt new file mode 100644 index 0000000..2dba261 --- /dev/null +++ b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/Channel.kt @@ -0,0 +1,94 @@ +/** + * Copyright (C) 2018 Sysdata Digital, S.r.l. + * + * 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. + */ +package it.sysdata.ktandroidarchitecturecore.interactor + +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.LiveData +import androidx.lifecycle.Observer +import androidx.paging.DataSource +import androidx.paging.PagedList + +/** + * [Channel] allow to define [Datasource] and [MutableLiveData] for handle the success, loading and failure case + * + * of Use Case and it allow to set a function for mapping Model into UiModel + * + */ +abstract class Channel{ + + protected var liveData: LiveData>? = null + + protected lateinit var dataSource: DataSource + + /** + * Define the function that will use for handle the result + * + * @param owner for [liveData] + * @param body the function that will use for handle the result + */ + fun observe(owner: LifecycleOwner, body: (PagedList?) -> Unit) { + liveData?.observe(owner, Observer(body)) + } + + abstract fun initDatasource(datas: List) + + abstract fun postInitial() + + abstract fun postNext() + + class ChannelBuilder internal constructor(private val channel: Channel) { + /** + * Set map function for [Channel] + * + * @return [Builder] instance + */ + fun buildWithUiModel(): Channel { + return channel + + } + } + + + /** + * Use this class for create a instance of [Channel] + */ + class Builder { + lateinit var channel : Channel + + fun channel(channelClass: Class) : Builder where T : Channel{ + val channel = channelClass.newInstance() + this.channel = channel + return this + } + + /** + * Set use case for [Channel] + * @param dataSourceClass Java class of use case + * + * @return [ChannelBuilder] instance + */ + + fun dataSource(dataSourceClass: Class): ChannelBuilder where T : DataSource { + channel.dataSource = dataSourceClass.newInstance() + return ChannelBuilder(channel) + } + + + } + +} + + diff --git a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/PositionalChannel.kt b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/PositionalChannel.kt new file mode 100644 index 0000000..8de752f --- /dev/null +++ b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/PositionalChannel.kt @@ -0,0 +1,85 @@ +/** + * Copyright (C) 2018 Sysdata Digital, S.r.l. + * + * 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. + */ +package it.sysdata.ktandroidarchitecturecore.interactor + +import androidx.paging.DataSource +import androidx.paging.LivePagedListBuilder +import androidx.paging.PagedList +import androidx.paging.PositionalDataSource + +/** + * [PositionalChannel] allow to define [Datasource] and [MutableLiveData] for handle the success, loading and failure case + * + * of Use Case and it allow to set a function for mapping Model into UiModel + * + */ +open class PositionalChannel : Channel() { + + override fun initDatasource(datas: List){ + val pageSize = datas.size / 4 + (dataSource as BasePositionalDatasource).initDataSource(datas, pageSize) + val config = PagedList.Config.Builder() + .setPageSize(pageSize) + .setInitialLoadSizeHint(pageSize * 2) + .setEnablePlaceholders(false) + .build() + val dataSourceFactory = object : DataSource.Factory() { + override fun create(): DataSource { + return dataSource + } + } + liveData = LivePagedListBuilder(dataSourceFactory, config).build() + } + + override fun postInitial(){ + (dataSource as BasePositionalDatasource).loadInitial( + PositionalDataSource.LoadInitialParams( + 0, + 10, + 10, + false + ), + object: PositionalDataSource.LoadInitialCallback(){ + override fun onResult(data: MutableList, position: Int, totalCount: Int) { +// liveData.postValue(data) + } + + override fun onResult(data: MutableList, position: Int) { +// liveData.postValue(data) + } + + } + ) + } + + override fun postNext(){ + (dataSource as BasePositionalDatasource).loadRange( + PositionalDataSource.LoadRangeParams( + 0, + 0 + ), + object: PositionalDataSource.LoadRangeCallback(){ + override fun onResult(data: MutableList) { +// liveData.postValue(data) + } + + } + ) + } + +} + + From 1c9778be414f2e35e9f7ea6a30fcc67491b91132 Mon Sep 17 00:00:00 2001 From: Salvatore Ranieri Date: Mon, 13 May 2019 14:58:18 +0200 Subject: [PATCH 02/10] refactoring channel --- .../ktandroidarchitecture/ui/LoginActivity.kt | 19 ++++- .../ktandroidarchitecture/ui/NoteChannel.kt | 5 -- .../viewmodel/LoginViewModel.kt | 13 ++- .../interactor/BaseItemKeyedDatasource.kt | 82 ++++++++++++++++++ .../interactor/BasePositionalDatasource.kt | 10 +-- .../interactor/Channel.kt | 67 +++++---------- .../interactor/DataSourceChannel.kt | 80 +++++++++++++++++ .../interactor/PositionalChannel.kt | 85 ------------------- 8 files changed, 206 insertions(+), 155 deletions(-) delete mode 100644 app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/NoteChannel.kt create mode 100644 ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BaseItemKeyedDatasource.kt create mode 100644 ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/DataSourceChannel.kt delete mode 100644 ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/PositionalChannel.kt diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt index 275ab77..9a21269 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt @@ -5,17 +5,18 @@ import android.os.Bundle import android.text.Editable import android.text.TextWatcher import android.view.View -import android.widget.LinearLayout import android.widget.Toast import androidx.fragment.app.FragmentActivity import androidx.lifecycle.ViewModelProviders import androidx.paging.PagedList import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView import com.sysdata.kt.ktandroidarchitecture.R import com.sysdata.kt.ktandroidarchitecture.repository.model.UIUserLogged import com.sysdata.kt.ktandroidarchitecture.usecase.LoginActionParams import com.sysdata.kt.ktandroidarchitecture.viewmodel.LoginViewModel import it.sysdata.ktandroidarchitecturecore.exception.Failure +import it.sysdata.ktandroidarchitecturecore.interactor.DataSourceChannel import kotlinx.android.synthetic.main.activity_login.* class LoginActivity : FragmentActivity(), View.OnClickListener, TextWatcher { @@ -41,16 +42,26 @@ class LoginActivity : FragmentActivity(), View.OnClickListener, TextWatcher { viewModel?.actionLogin?.observeFailure(this, ::onLoginFailed) - viewModel?.channelNotes?.initDatasource(listOf(Note(), Note(), Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note())) + viewModel?.channelNotes?.let { + if(it is DataSourceChannel<*, *>){ + it as DataSourceChannel<*, Note> + it.initDatasource(listOf(Note(), Note(), Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note())) + } + } adapter = PagedListAdapterImpl { - Toast.makeText(this, "note : $it", Toast.LENGTH_SHORT).show() + viewModel?.channelPostNotes?.postData(it) } - recycler_view.layoutManager = LinearLayoutManager(this, LinearLayout.VERTICAL, false) + recycler_view.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false) recycler_view.adapter = adapter viewModel?.channelNotes?.observe(this,::onPostNote) + viewModel?.channelPostNotes?.observe(this, ::onReceivePost) + } + + private fun onReceivePost(note: Note?) { + Toast.makeText(this, "note : $note", Toast.LENGTH_SHORT).show() } private fun onPostNote(list: PagedList?) { diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/NoteChannel.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/NoteChannel.kt deleted file mode 100644 index 626e1a2..0000000 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/NoteChannel.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.sysdata.kt.ktandroidarchitecture.ui - -import it.sysdata.ktandroidarchitecturecore.interactor.PositionalChannel - -class NoteChannel:PositionalChannel() \ No newline at end of file diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/viewmodel/LoginViewModel.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/viewmodel/LoginViewModel.kt index 0c5bce5..e365925 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/viewmodel/LoginViewModel.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/viewmodel/LoginViewModel.kt @@ -3,14 +3,10 @@ package com.sysdata.kt.ktandroidarchitecture.viewmodel import com.sysdata.kt.ktandroidarchitecture.repository.model.UIUserLogged import com.sysdata.kt.ktandroidarchitecture.repository.model.UserLogged import com.sysdata.kt.ktandroidarchitecture.ui.Note -import com.sysdata.kt.ktandroidarchitecture.ui.NoteChannel import com.sysdata.kt.ktandroidarchitecture.ui.NoteDataSource import com.sysdata.kt.ktandroidarchitecture.usecase.LoginActionParams import com.sysdata.kt.ktandroidarchitecture.usecase.LoginUseCase -import it.sysdata.ktandroidarchitecturecore.interactor.Action -import it.sysdata.ktandroidarchitecturecore.interactor.BasePositionalDatasource -import it.sysdata.ktandroidarchitecturecore.interactor.Channel -import it.sysdata.ktandroidarchitecturecore.interactor.PositionalChannel +import it.sysdata.ktandroidarchitecturecore.interactor.* import it.sysdata.ktandroidarchitecturecore.platform.BaseViewModel class LoginViewModel: BaseViewModel() { @@ -19,8 +15,9 @@ class LoginViewModel: BaseViewModel() { .useCase(LoginUseCase::class.java) .buildWithUiModel { UIUserLogged(it.username) } - val channelNotes = Channel.Builder() - .channel(NoteChannel::class.java) + val channelNotes = DataSourceChannel.Builder() .dataSource(NoteDataSource::class.java) - .buildWithUiModel() + .build() + + val channelPostNotes = Channel() } \ No newline at end of file diff --git a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BaseItemKeyedDatasource.kt b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BaseItemKeyedDatasource.kt new file mode 100644 index 0000000..dec666a --- /dev/null +++ b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BaseItemKeyedDatasource.kt @@ -0,0 +1,82 @@ +package it.sysdata.ktandroidarchitecturecore.interactor + +import androidx.paging.* + + +open class BaseItemKeyedDatasource: ItemKeyedDataSource(){ + + private var defaultLoadSize: Int? = null + private lateinit var datas: List + + override fun loadAfter(params: LoadParams, callback: LoadCallback) { + + val requestedLoadSize = params.requestedLoadSize + val key = params.key + + val item = getItemForKey(key) + var startPosition = datas.indexOf(item) + startPosition = if(startPosition < datas.size) startPosition else 0 + + val subList = getSubList(startPosition, requestedLoadSize) + + callback.onResult(subList) + } + + override fun loadBefore(params: LoadParams, callback: LoadCallback) { + val requestedLoadSize = params.requestedLoadSize + val key = params.key + + val item = getItemForKey(key) + var startPosition = datas.indexOf(item) - requestedLoadSize + startPosition = if(startPosition > 0) startPosition else 0 + + val subList = getSubList(startPosition, requestedLoadSize) + + callback.onResult(subList) + } + + override fun getKey(item: Data): Key { + return item.hashCode() as Key + } + + override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback) { + val placeholdersEnabled = params.placeholdersEnabled + val requestedInitialKey = params.requestedInitialKey + var requestedLoadSize = params.requestedLoadSize + + val item = requestedInitialKey?.let { getItemForKey(it) } + var startPosition = item?.let {datas.indexOf(item)} ?: 0 + startPosition = if(startPosition < datas.size) startPosition else 0 + + defaultLoadSize?.let { + if(requestedLoadSize > it){ + requestedLoadSize = it + } + } + val subList = getSubList(startPosition, requestedLoadSize) + + if (placeholdersEnabled) { + callback.onResult(subList, startPosition, requestedLoadSize) + } else { + callback.onResult(subList) + } + } + + // Override this method to use another key + private fun getItemForKey(key: Key):Data{ + return datas.first { it.hashCode() == key.hashCode() } + } + + private fun getSubList(startPosition: Int, defaultLoadSize: Int): List { + if(startPosition >= datas.size){ + return datas.subList(datas.size - 1, datas.size - 1) + } + val endIndex = if (startPosition + defaultLoadSize <= datas.size) startPosition + defaultLoadSize else datas.size - 1 + return datas.subList(startPosition, endIndex) + } + + fun init(datas: List, pageSize: Int) { + this.datas = datas + this.defaultLoadSize = pageSize + } +} \ No newline at end of file diff --git a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BasePositionalDatasource.kt b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BasePositionalDatasource.kt index a183506..f99e09b 100644 --- a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BasePositionalDatasource.kt +++ b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BasePositionalDatasource.kt @@ -9,11 +9,6 @@ open class BasePositionalDatasource: PositionalDataSource(){ private lateinit var datas: List private var currentPosition: Int = 0 - fun initDataSource(datas: List, defaultLoadSize: Int? = null){ - this.datas = datas - this.defaultLoadSize = defaultLoadSize - } - override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback) { val loadSize = params.loadSize val startPosition = params.startPosition @@ -56,4 +51,9 @@ open class BasePositionalDatasource: PositionalDataSource(){ currentPosition = endIndex return datas.subList(startPosition, endIndex) } + + fun init(datas: List, pageSize: Int) { + this.datas = datas + this.defaultLoadSize = pageSize + } } \ No newline at end of file diff --git a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/Channel.kt b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/Channel.kt index 2dba261..79bca44 100644 --- a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/Channel.kt +++ b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/Channel.kt @@ -17,78 +17,49 @@ package it.sysdata.ktandroidarchitecturecore.interactor import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData import androidx.lifecycle.Observer -import androidx.paging.DataSource -import androidx.paging.PagedList /** - * [Channel] allow to define [Datasource] and [MutableLiveData] for handle the success, loading and failure case - * - * of Use Case and it allow to set a function for mapping Model into UiModel + * [Channel] allow to observe a [MutableLiveData] used to post datas time by time * */ -abstract class Channel{ - - protected var liveData: LiveData>? = null +open class Channel{ - protected lateinit var dataSource: DataSource + var liveData: LiveData = MutableLiveData() /** - * Define the function that will use for handle the result + * Define the function that will use for handle the data posted by the channel * * @param owner for [liveData] * @param body the function that will use for handle the result */ - fun observe(owner: LifecycleOwner, body: (PagedList?) -> Unit) { - liveData?.observe(owner, Observer(body)) + fun observe(owner: LifecycleOwner, body: (Data?) -> Unit) { + liveData.observe(owner, Observer(body)) } - abstract fun initDatasource(datas: List) - - abstract fun postInitial() - - abstract fun postNext() - - class ChannelBuilder internal constructor(private val channel: Channel) { - /** - * Set map function for [Channel] - * - * @return [Builder] instance - */ - fun buildWithUiModel(): Channel { - return channel - + /** + * Use this method to post datas through channel + * + * @param data Data to be posted on the livedata + */ + fun postData(data: Data){ + val postLiveData = liveData + if (postLiveData is MutableLiveData) { + postLiveData.postValue(data) } } - /** * Use this class for create a instance of [Channel] */ - class Builder { - lateinit var channel : Channel - - fun channel(channelClass: Class) : Builder where T : Channel{ - val channel = channelClass.newInstance() - this.channel = channel - return this - } + class ChannelBuilder internal constructor(private val channel: Channel) { - /** - * Set use case for [Channel] - * @param dataSourceClass Java class of use case - * - * @return [ChannelBuilder] instance - */ + fun build(): Channel { + return channel - fun dataSource(dataSourceClass: Class): ChannelBuilder where T : DataSource { - channel.dataSource = dataSourceClass.newInstance() - return ChannelBuilder(channel) } - - } - } diff --git a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/DataSourceChannel.kt b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/DataSourceChannel.kt new file mode 100644 index 0000000..047818e --- /dev/null +++ b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/DataSourceChannel.kt @@ -0,0 +1,80 @@ +/** + * Copyright (C) 2018 Sysdata Digital, S.r.l. + * + * 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. + */ +package it.sysdata.ktandroidarchitecturecore.interactor + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.paging.DataSource +import androidx.paging.LivePagedListBuilder +import androidx.paging.PagedList + +/** + * [DataSourceChannel] allow to define [Datasource] and [MutableLiveData] for handle the success, loading and failure case + * + * of Use Case and it allow to set a function for mapping Model into UiModel + * + */ +class DataSourceChannel: Channel>(){ + + private lateinit var dataSource: DataSource + + fun initDatasource(datas: List, pageSize: Int = datas.size / 4, initialLoadSizeHint: Int = pageSize * 2, placeHolderEnabled: Boolean = false){ + val dataSourceBase = dataSource + this.liveData = initLiveData(dataSource, pageSize, initialLoadSizeHint, placeHolderEnabled) + // TODO: check this + if (dataSourceBase is BasePositionalDatasource) { + dataSourceBase.init(datas, pageSize) + } else if(dataSourceBase is BaseItemKeyedDatasource){ + dataSourceBase.init(datas, pageSize) + } + this.liveData = initLiveData(dataSource, pageSize, initialLoadSizeHint, placeHolderEnabled) + } + + private fun initLiveData(dataSource: DataSource, pageSize: Int, initialLoadSizeHint: Int, placeHolderEnabled: Boolean): LiveData> { + val config = PagedList.Config.Builder() + .setPageSize(pageSize) + .setInitialLoadSizeHint(initialLoadSizeHint) + .setEnablePlaceholders(placeHolderEnabled) + .build() + val dataSourceFactory = object : DataSource.Factory() { + override fun create(): DataSource { + return dataSource + } + } + return LivePagedListBuilder(dataSourceFactory, config).build() + } + + + /** + * Use this class for create a instance of [DataSourceChannel] + */ + class Builder { + lateinit var channel : DataSourceChannel + + fun dataSource(dataSourceClass: Class): ChannelBuilder> where T : DataSource { + return this.dataSource(dataSourceClass.newInstance()) + } + + fun dataSource(dataSource: DataSource): ChannelBuilder> where T : DataSource { + channel = DataSourceChannel() + channel.dataSource = dataSource + return ChannelBuilder(channel) + } + } + +} + + diff --git a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/PositionalChannel.kt b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/PositionalChannel.kt deleted file mode 100644 index 8de752f..0000000 --- a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/PositionalChannel.kt +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Copyright (C) 2018 Sysdata Digital, S.r.l. - * - * 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. - */ -package it.sysdata.ktandroidarchitecturecore.interactor - -import androidx.paging.DataSource -import androidx.paging.LivePagedListBuilder -import androidx.paging.PagedList -import androidx.paging.PositionalDataSource - -/** - * [PositionalChannel] allow to define [Datasource] and [MutableLiveData] for handle the success, loading and failure case - * - * of Use Case and it allow to set a function for mapping Model into UiModel - * - */ -open class PositionalChannel : Channel() { - - override fun initDatasource(datas: List){ - val pageSize = datas.size / 4 - (dataSource as BasePositionalDatasource).initDataSource(datas, pageSize) - val config = PagedList.Config.Builder() - .setPageSize(pageSize) - .setInitialLoadSizeHint(pageSize * 2) - .setEnablePlaceholders(false) - .build() - val dataSourceFactory = object : DataSource.Factory() { - override fun create(): DataSource { - return dataSource - } - } - liveData = LivePagedListBuilder(dataSourceFactory, config).build() - } - - override fun postInitial(){ - (dataSource as BasePositionalDatasource).loadInitial( - PositionalDataSource.LoadInitialParams( - 0, - 10, - 10, - false - ), - object: PositionalDataSource.LoadInitialCallback(){ - override fun onResult(data: MutableList, position: Int, totalCount: Int) { -// liveData.postValue(data) - } - - override fun onResult(data: MutableList, position: Int) { -// liveData.postValue(data) - } - - } - ) - } - - override fun postNext(){ - (dataSource as BasePositionalDatasource).loadRange( - PositionalDataSource.LoadRangeParams( - 0, - 0 - ), - object: PositionalDataSource.LoadRangeCallback(){ - override fun onResult(data: MutableList) { -// liveData.postValue(data) - } - - } - ) - } - -} - - From b4e56b5e09dae7e826af9460bb819e8b13804f78 Mon Sep 17 00:00:00 2001 From: Salvatore Ranieri Date: Mon, 13 May 2019 15:44:43 +0200 Subject: [PATCH 03/10] updated documentation --- .../ktandroidarchitecture/ui/LoginActivity.kt | 7 +++- .../kt/ktandroidarchitecture/ui/Note.kt | 2 +- .../interactor/BaseItemKeyedDatasource.kt | 4 +-- .../interactor/Channel.kt | 2 +- .../interactor/DataSourceChannel.kt | 33 +++++++++++++++---- 5 files changed, 37 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt index 9a21269..21c3410 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt @@ -44,8 +44,13 @@ class LoginActivity : FragmentActivity(), View.OnClickListener, TextWatcher { viewModel?.channelNotes?.let { if(it is DataSourceChannel<*, *>){ + // TODO: check this code, the cast is unsafe it as DataSourceChannel<*, Note> - it.initDatasource(listOf(Note(), Note(), Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note(),Note())) + val notes = mutableListOf() + for(i in 0 until 32){ + notes.add(Note(i)) + } + it.initDatasource(notes) } } diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/Note.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/Note.kt index 1f9a514..abe2a7f 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/Note.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/Note.kt @@ -3,7 +3,7 @@ package com.sysdata.kt.ktandroidarchitecture.ui import androidx.recyclerview.widget.DiffUtil import java.util.* -data class Note(val noteId: String = UUID.randomUUID().toString()) { +data class Note(val index:Int, val noteId: String = UUID.randomUUID().toString()) { companion object { val DiffCallback = object : DiffUtil.ItemCallback() { override fun areItemsTheSame(oldItem: Note, newItem: Note): Boolean diff --git a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BaseItemKeyedDatasource.kt b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BaseItemKeyedDatasource.kt index dec666a..7078632 100644 --- a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BaseItemKeyedDatasource.kt +++ b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BaseItemKeyedDatasource.kt @@ -6,7 +6,7 @@ import androidx.paging.* open class BaseItemKeyedDatasource: ItemKeyedDataSource(){ private var defaultLoadSize: Int? = null - private lateinit var datas: List + protected lateinit var datas: List override fun loadAfter(params: LoadParams, callback: LoadCallback) { @@ -63,7 +63,7 @@ open class BaseItemKeyedDatasource: ItemKeyedDataSource{ * Define the function that will use for handle the data posted by the channel * * @param owner for [liveData] - * @param body the function that will use for handle the result + * @param body the function that will use for handle the data posted by the channel */ fun observe(owner: LifecycleOwner, body: (Data?) -> Unit) { liveData.observe(owner, Observer(body)) diff --git a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/DataSourceChannel.kt b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/DataSourceChannel.kt index 047818e..23718a2 100644 --- a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/DataSourceChannel.kt +++ b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/DataSourceChannel.kt @@ -24,25 +24,46 @@ import androidx.paging.PagedList /** * [DataSourceChannel] allow to define [Datasource] and [MutableLiveData] for handle the success, loading and failure case * - * of Use Case and it allow to set a function for mapping Model into UiModel * */ class DataSourceChannel: Channel>(){ private lateinit var dataSource: DataSource - fun initDatasource(datas: List, pageSize: Int = datas.size / 4, initialLoadSizeHint: Int = pageSize * 2, placeHolderEnabled: Boolean = false){ + /** + * + * This method is used to initialize the datasource associated with the channel + * and the live data for the paged lists associated with the datasource + * + * @param datas List, list of datas used as dataset of the datasource, + * if your datasource doesn't need an initial dataset don't set this parameter and set the pagesize + * @param pageSize Int, size of the page to load + * @param initialLoadSizeHint Int, size of the initial page + * @param placeHolderEnabled Boolean + */ + fun initDatasource(datas: List? = null, pageSize: Int = (datas?.size ?: 0) / 4, initialLoadSizeHint: Int = pageSize * 2, placeHolderEnabled: Boolean = false){ val dataSourceBase = dataSource this.liveData = initLiveData(dataSource, pageSize, initialLoadSizeHint, placeHolderEnabled) // TODO: check this - if (dataSourceBase is BasePositionalDatasource) { - dataSourceBase.init(datas, pageSize) - } else if(dataSourceBase is BaseItemKeyedDatasource){ - dataSourceBase.init(datas, pageSize) + if (datas != null && datas.isNotEmpty()) { + if (dataSourceBase is BasePositionalDatasource) { + dataSourceBase.init(datas, pageSize) + } else if(dataSourceBase is BaseItemKeyedDatasource){ + dataSourceBase.init(datas, pageSize) + } } this.liveData = initLiveData(dataSource, pageSize, initialLoadSizeHint, placeHolderEnabled) } + /** + * this method is used to create a livedata of paged list based on the channel's datasource + * + * @param dataSource DataSource + * @param pageSize Int + * @param initialLoadSizeHint Int + * @param placeHolderEnabled Boolean + * @return LiveData> + */ private fun initLiveData(dataSource: DataSource, pageSize: Int, initialLoadSizeHint: Int, placeHolderEnabled: Boolean): LiveData> { val config = PagedList.Config.Builder() .setPageSize(pageSize) From c019bb8a1582ae9f74ad9c994838feecdd9580f7 Mon Sep 17 00:00:00 2001 From: Salvatore Ranieri Date: Mon, 13 May 2019 15:59:06 +0200 Subject: [PATCH 04/10] fixed error in case of placeholder enabled for base datasources --- .../com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt | 2 +- .../interactor/BaseItemKeyedDatasource.kt | 2 +- .../interactor/BasePositionalDatasource.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt index 21c3410..49d341d 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt @@ -47,7 +47,7 @@ class LoginActivity : FragmentActivity(), View.OnClickListener, TextWatcher { // TODO: check this code, the cast is unsafe it as DataSourceChannel<*, Note> val notes = mutableListOf() - for(i in 0 until 32){ + for(i in 0 until 500){ notes.add(Note(i)) } it.initDatasource(notes) diff --git a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BaseItemKeyedDatasource.kt b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BaseItemKeyedDatasource.kt index 7078632..50298e3 100644 --- a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BaseItemKeyedDatasource.kt +++ b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BaseItemKeyedDatasource.kt @@ -56,7 +56,7 @@ open class BaseItemKeyedDatasource: ItemKeyedDataSource: PositionalDataSource(){ } val subList = getSubList(startPosition, requestedLoadSize) if(placeholdersEnabled){ - callback.onResult(subList, startPosition, requestedLoadSize) + callback.onResult(subList, startPosition, datas.size) } else { callback.onResult(subList, startPosition) } From d1db98c88efb8ed693a910e1823d7ac7c88265e1 Mon Sep 17 00:00:00 2001 From: Salvatore Ranieri Date: Mon, 13 May 2019 17:17:30 +0200 Subject: [PATCH 05/10] added test mock datasource --- .../ui/TestDataSource.kt | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/TestDataSource.kt diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/TestDataSource.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/TestDataSource.kt new file mode 100644 index 0000000..80149a7 --- /dev/null +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/TestDataSource.kt @@ -0,0 +1,58 @@ +package com.sysdata.kt.ktandroidarchitecture.ui + +import androidx.paging.ItemKeyedDataSource + +class TestDataSource: ItemKeyedDataSource(){ + + private val datas = listOf(Note(1), Note(2), Note(3), Note(4), Note(5)) + + override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback) { + val requestedLoadSize = params.requestedLoadSize + val requestedInitialKey = params.requestedInitialKey ?: 0 + + val initItem = datas.firstOrNull { it.index == requestedInitialKey } + val initIndex = initItem?.let {datas.indexOf(initItem)} ?: 0 + val newData = getSubList(initIndex, initIndex + requestedLoadSize) + callback.onResult(newData) + } + + private fun getSubList(initIndex: Int, finalIndex: Int): MutableList { + val newData = mutableListOf() + for (i in initIndex until finalIndex) { + newData.add(datas[i % datas.size]) + } + return newData + } + + override fun loadAfter(params: LoadParams, callback: LoadCallback) { + val key = params.key + val requestedLoadSize = params.requestedLoadSize + + val initItem = datas.firstOrNull { it.index == key } + val initIndex = initItem?.let {datas.indexOf(initItem)} ?: 0 + val newData = getSubList(initIndex, initIndex + requestedLoadSize) + callback.onResult(newData) + } + + override fun loadBefore(params: LoadParams, callback: LoadCallback) { + val key = params.key + val requestedLoadSize = params.requestedLoadSize + + val initItem = datas.firstOrNull { it.index == key } + var initIndex = initItem?.let {datas.indexOf(initItem)} ?: 0 + var finalIndex = initIndex + if(initIndex - requestedLoadSize >= 0){ + initIndex -= requestedLoadSize + } else { + initIndex = 0 + finalIndex = initIndex + requestedLoadSize + } + val newData = getSubList(initIndex, finalIndex) + callback.onResult(newData) + } + + override fun getKey(item: Note): Int { + return item.index + } + +} \ No newline at end of file From a73065ee0a78b7939bf0b100dd35edaf9101d52f Mon Sep 17 00:00:00 2001 From: Salvatore Ranieri Date: Fri, 17 May 2019 12:03:06 +0200 Subject: [PATCH 06/10] updated channel implementation --- .../kt/ktandroidarchitecture/DIUtils.kt | 18 ++++++++++++++++++ .../repository/AuthRepository.kt | 12 ++++++++++++ .../ktandroidarchitecture/ui/LoginActivity.kt | 19 +++++++++---------- .../viewmodel/LoginViewModel.kt | 6 ++++-- .../interactor/BaseItemKeyedDatasource.kt | 5 +++++ .../interactor/Channel.kt | 10 ---------- .../interactor/DataSourceChannel.kt | 17 +++++++++++++---- 7 files changed, 61 insertions(+), 26 deletions(-) create mode 100644 app/src/main/java/com/sysdata/kt/ktandroidarchitecture/DIUtils.kt diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/DIUtils.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/DIUtils.kt new file mode 100644 index 0000000..8c4448a --- /dev/null +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/DIUtils.kt @@ -0,0 +1,18 @@ +package com.sysdata.kt.ktandroidarchitecture + +import com.sysdata.kt.ktandroidarchitecture.repository.AuthRepository +import com.sysdata.kt.ktandroidarchitecture.ui.Note +import it.sysdata.ktandroidarchitecturecore.interactor.Channel + +class DIUtils { + + private object Holder { + val INSTANCE = Channel() + } + + companion object { + val channel: Channel by lazy { + Holder.INSTANCE + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/repository/AuthRepository.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/repository/AuthRepository.kt index ce8f808..031c934 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/repository/AuthRepository.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/repository/AuthRepository.kt @@ -1,6 +1,8 @@ package com.sysdata.kt.ktandroidarchitecture.repository +import com.sysdata.kt.ktandroidarchitecture.DIUtils import com.sysdata.kt.ktandroidarchitecture.repository.model.UserLogged +import com.sysdata.kt.ktandroidarchitecture.ui.Note import it.sysdata.ktandroidarchitecturecore.BaseRepository import it.sysdata.ktandroidarchitecturecore.exception.Failure import it.sysdata.ktandroidarchitecturecore.functional.Either @@ -23,4 +25,14 @@ class AuthRepository:BaseRepository() { else Either.Right(UserLogged(email)) } + +/* TODO: check this code + private val datas = listOf(Note(1), Note(2), Note(3), Note(4), Note(5)) + + fun startSendingNotes(interval: Int = 5000){ + //TODO: track index and start recurring each 5 seconds + //DIUtils.channel.postData() +// DIUtils.dataSourceChannel.observeLoadDataRequest() + } + */ } \ No newline at end of file diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt index 49d341d..2882c7c 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt @@ -42,18 +42,17 @@ class LoginActivity : FragmentActivity(), View.OnClickListener, TextWatcher { viewModel?.actionLogin?.observeFailure(this, ::onLoginFailed) - viewModel?.channelNotes?.let { - if(it is DataSourceChannel<*, *>){ - // TODO: check this code, the cast is unsafe - it as DataSourceChannel<*, Note> - val notes = mutableListOf() - for(i in 0 until 500){ - notes.add(Note(i)) - } - it.initDatasource(notes) - } + /* + val notes = mutableListOf() + for(i in 0 until 500){ + notes.add(Note(i)) } + viewModel?.channelNotes?.initDatasource(notes) + */ + + viewModel?.channelNotes?.initDatasource(pageSize = 10) + adapter = PagedListAdapterImpl { viewModel?.channelPostNotes?.postData(it) } diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/viewmodel/LoginViewModel.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/viewmodel/LoginViewModel.kt index e365925..122489c 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/viewmodel/LoginViewModel.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/viewmodel/LoginViewModel.kt @@ -1,9 +1,11 @@ package com.sysdata.kt.ktandroidarchitecture.viewmodel +import com.sysdata.kt.ktandroidarchitecture.DIUtils import com.sysdata.kt.ktandroidarchitecture.repository.model.UIUserLogged import com.sysdata.kt.ktandroidarchitecture.repository.model.UserLogged import com.sysdata.kt.ktandroidarchitecture.ui.Note import com.sysdata.kt.ktandroidarchitecture.ui.NoteDataSource +import com.sysdata.kt.ktandroidarchitecture.ui.TestDataSource import com.sysdata.kt.ktandroidarchitecture.usecase.LoginActionParams import com.sysdata.kt.ktandroidarchitecture.usecase.LoginUseCase import it.sysdata.ktandroidarchitecturecore.interactor.* @@ -16,8 +18,8 @@ class LoginViewModel: BaseViewModel() { .buildWithUiModel { UIUserLogged(it.username) } val channelNotes = DataSourceChannel.Builder() - .dataSource(NoteDataSource::class.java) + .dataSource(TestDataSource::class.java) .build() - val channelPostNotes = Channel() + val channelPostNotes = DIUtils.channel } \ No newline at end of file diff --git a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BaseItemKeyedDatasource.kt b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BaseItemKeyedDatasource.kt index 50298e3..144e299 100644 --- a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BaseItemKeyedDatasource.kt +++ b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BaseItemKeyedDatasource.kt @@ -1,6 +1,7 @@ package it.sysdata.ktandroidarchitecturecore.interactor import androidx.paging.* +import androidx.recyclerview.widget.DiffUtil open class BaseItemKeyedDatasource: ItemKeyedDataSource(){ @@ -20,6 +21,10 @@ open class BaseItemKeyedDatasource: ItemKeyedDataSource, callback: LoadCallback) { diff --git a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/Channel.kt b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/Channel.kt index 469ee22..0067627 100644 --- a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/Channel.kt +++ b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/Channel.kt @@ -50,16 +50,6 @@ open class Channel{ } } - /** - * Use this class for create a instance of [Channel] - */ - class ChannelBuilder internal constructor(private val channel: Channel) { - - fun build(): Channel { - return channel - - } - } } diff --git a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/DataSourceChannel.kt b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/DataSourceChannel.kt index 23718a2..a622f30 100644 --- a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/DataSourceChannel.kt +++ b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/DataSourceChannel.kt @@ -44,15 +44,14 @@ class DataSourceChannel: Channel>(){ fun initDatasource(datas: List? = null, pageSize: Int = (datas?.size ?: 0) / 4, initialLoadSizeHint: Int = pageSize * 2, placeHolderEnabled: Boolean = false){ val dataSourceBase = dataSource this.liveData = initLiveData(dataSource, pageSize, initialLoadSizeHint, placeHolderEnabled) - // TODO: check this if (datas != null && datas.isNotEmpty()) { + // TODO: check this if (dataSourceBase is BasePositionalDatasource) { dataSourceBase.init(datas, pageSize) } else if(dataSourceBase is BaseItemKeyedDatasource){ dataSourceBase.init(datas, pageSize) } } - this.liveData = initLiveData(dataSource, pageSize, initialLoadSizeHint, placeHolderEnabled) } /** @@ -78,6 +77,16 @@ class DataSourceChannel: Channel>(){ return LivePagedListBuilder(dataSourceFactory, config).build() } + /** + * Use this class for create a instance of [Channel] + */ + class ChannelBuilder internal constructor(private val channel: Channel>) { + + fun build(): DataSourceChannel { + return channel as DataSourceChannel + } + } + /** * Use this class for create a instance of [DataSourceChannel] @@ -85,11 +94,11 @@ class DataSourceChannel: Channel>(){ class Builder { lateinit var channel : DataSourceChannel - fun dataSource(dataSourceClass: Class): ChannelBuilder> where T : DataSource { + fun dataSource(dataSourceClass: Class): ChannelBuilder where T : DataSource { return this.dataSource(dataSourceClass.newInstance()) } - fun dataSource(dataSource: DataSource): ChannelBuilder> where T : DataSource { + fun dataSource(dataSource: DataSource): ChannelBuilder where T : DataSource { channel = DataSourceChannel() channel.dataSource = dataSource return ChannelBuilder(channel) From 4e884b298b819cadb2eb6ff0e6ac8561dcc09092 Mon Sep 17 00:00:00 2001 From: Salvatore Ranieri Date: Fri, 17 May 2019 12:06:56 +0200 Subject: [PATCH 07/10] moved datasource outside of interactor --- .../com/sysdata/kt/ktandroidarchitecture/ui/NoteDataSource.kt | 2 +- .../{interactor => }/BaseItemKeyedDatasource.kt | 3 +-- .../{interactor => }/BasePositionalDatasource.kt | 2 +- .../ktandroidarchitecturecore/interactor/DataSourceChannel.kt | 2 ++ 4 files changed, 5 insertions(+), 4 deletions(-) rename ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/{interactor => }/BaseItemKeyedDatasource.kt (96%) rename ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/{interactor => }/BasePositionalDatasource.kt (97%) diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/NoteDataSource.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/NoteDataSource.kt index cbbbe90..95f64e5 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/NoteDataSource.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/NoteDataSource.kt @@ -1,5 +1,5 @@ package com.sysdata.kt.ktandroidarchitecture.ui -import it.sysdata.ktandroidarchitecturecore.interactor.BasePositionalDatasource +import it.sysdata.ktandroidarchitecturecore.BasePositionalDatasource class NoteDataSource: BasePositionalDatasource() \ No newline at end of file diff --git a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BaseItemKeyedDatasource.kt b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/BaseItemKeyedDatasource.kt similarity index 96% rename from ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BaseItemKeyedDatasource.kt rename to ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/BaseItemKeyedDatasource.kt index 144e299..901f713 100644 --- a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BaseItemKeyedDatasource.kt +++ b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/BaseItemKeyedDatasource.kt @@ -1,7 +1,6 @@ -package it.sysdata.ktandroidarchitecturecore.interactor +package it.sysdata.ktandroidarchitecturecore import androidx.paging.* -import androidx.recyclerview.widget.DiffUtil open class BaseItemKeyedDatasource: ItemKeyedDataSource(){ diff --git a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BasePositionalDatasource.kt b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/BasePositionalDatasource.kt similarity index 97% rename from ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BasePositionalDatasource.kt rename to ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/BasePositionalDatasource.kt index 4251725..06070dc 100644 --- a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/BasePositionalDatasource.kt +++ b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/BasePositionalDatasource.kt @@ -1,4 +1,4 @@ -package it.sysdata.ktandroidarchitecturecore.interactor +package it.sysdata.ktandroidarchitecturecore import androidx.paging.PositionalDataSource diff --git a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/DataSourceChannel.kt b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/DataSourceChannel.kt index a622f30..29ccff6 100644 --- a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/DataSourceChannel.kt +++ b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/DataSourceChannel.kt @@ -20,6 +20,8 @@ import androidx.lifecycle.MutableLiveData import androidx.paging.DataSource import androidx.paging.LivePagedListBuilder import androidx.paging.PagedList +import it.sysdata.ktandroidarchitecturecore.BaseItemKeyedDatasource +import it.sysdata.ktandroidarchitecturecore.BasePositionalDatasource /** * [DataSourceChannel] allow to define [Datasource] and [MutableLiveData] for handle the success, loading and failure case From c707fb6e865bc2912d1aec76cd029d0143c60782 Mon Sep 17 00:00:00 2001 From: Salvatore Ranieri Date: Thu, 13 Jun 2019 11:34:05 +0200 Subject: [PATCH 08/10] - added copyright - added some comments - removed todoes --- .../kt/ktandroidarchitecture/DIUtils.kt | 1 - .../repository/AuthRepository.kt | 12 ---- .../ktandroidarchitecture/ui/LoginActivity.kt | 11 ---- .../BaseItemKeyedDatasource.kt | 66 +++++++++++++++++-- .../BasePositionalDatasource.kt | 43 +++++++++++- .../interactor/DataSourceChannel.kt | 1 - 6 files changed, 102 insertions(+), 32 deletions(-) diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/DIUtils.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/DIUtils.kt index 8c4448a..9f14c30 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/DIUtils.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/DIUtils.kt @@ -1,6 +1,5 @@ package com.sysdata.kt.ktandroidarchitecture -import com.sysdata.kt.ktandroidarchitecture.repository.AuthRepository import com.sysdata.kt.ktandroidarchitecture.ui.Note import it.sysdata.ktandroidarchitecturecore.interactor.Channel diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/repository/AuthRepository.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/repository/AuthRepository.kt index 031c934..ce8f808 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/repository/AuthRepository.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/repository/AuthRepository.kt @@ -1,8 +1,6 @@ package com.sysdata.kt.ktandroidarchitecture.repository -import com.sysdata.kt.ktandroidarchitecture.DIUtils import com.sysdata.kt.ktandroidarchitecture.repository.model.UserLogged -import com.sysdata.kt.ktandroidarchitecture.ui.Note import it.sysdata.ktandroidarchitecturecore.BaseRepository import it.sysdata.ktandroidarchitecturecore.exception.Failure import it.sysdata.ktandroidarchitecturecore.functional.Either @@ -25,14 +23,4 @@ class AuthRepository:BaseRepository() { else Either.Right(UserLogged(email)) } - -/* TODO: check this code - private val datas = listOf(Note(1), Note(2), Note(3), Note(4), Note(5)) - - fun startSendingNotes(interval: Int = 5000){ - //TODO: track index and start recurring each 5 seconds - //DIUtils.channel.postData() -// DIUtils.dataSourceChannel.observeLoadDataRequest() - } - */ } \ No newline at end of file diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt index 2882c7c..d323a0f 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt @@ -16,7 +16,6 @@ import com.sysdata.kt.ktandroidarchitecture.repository.model.UIUserLogged import com.sysdata.kt.ktandroidarchitecture.usecase.LoginActionParams import com.sysdata.kt.ktandroidarchitecture.viewmodel.LoginViewModel import it.sysdata.ktandroidarchitecturecore.exception.Failure -import it.sysdata.ktandroidarchitecturecore.interactor.DataSourceChannel import kotlinx.android.synthetic.main.activity_login.* class LoginActivity : FragmentActivity(), View.OnClickListener, TextWatcher { @@ -41,16 +40,6 @@ class LoginActivity : FragmentActivity(), View.OnClickListener, TextWatcher { viewModel?.actionLogin?.observe(this, ::onUserLoggged) viewModel?.actionLogin?.observeFailure(this, ::onLoginFailed) - - /* - val notes = mutableListOf() - for(i in 0 until 500){ - notes.add(Note(i)) - } - - viewModel?.channelNotes?.initDatasource(notes) - */ - viewModel?.channelNotes?.initDatasource(pageSize = 10) adapter = PagedListAdapterImpl { diff --git a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/BaseItemKeyedDatasource.kt b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/BaseItemKeyedDatasource.kt index 901f713..e3d9d70 100644 --- a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/BaseItemKeyedDatasource.kt +++ b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/BaseItemKeyedDatasource.kt @@ -1,13 +1,41 @@ +/** + * Copyright (C) 2019 Sysdata S.p.a. + * + * 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. + */ package it.sysdata.ktandroidarchitecturecore import androidx.paging.* - +/** + * A simple implementation of [ItemKeyedDataSource] + * + * @param Key:Any, the key to get the item from the datasource + * @param Data : Any, the data returned on each call + * @property defaultLoadSize Int?, the default size of a page + * @property datas List, the initial dataset + */ open class BaseItemKeyedDatasource: ItemKeyedDataSource(){ private var defaultLoadSize: Int? = null protected lateinit var datas: List + /** + * This method if called to load all the data after the position of the item with the given key + * + * @param params LoadParams + * @param callback LoadCallback + */ override fun loadAfter(params: LoadParams, callback: LoadCallback) { val requestedLoadSize = params.requestedLoadSize @@ -20,12 +48,14 @@ open class BaseItemKeyedDatasource: ItemKeyedDataSource + * @param callback LoadCallback + */ override fun loadBefore(params: LoadParams, callback: LoadCallback) { val requestedLoadSize = params.requestedLoadSize val key = params.key @@ -39,10 +69,21 @@ open class BaseItemKeyedDatasource: ItemKeyedDataSource + * @param callback LoadInitialCallback + */ override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback) { val placeholdersEnabled = params.placeholdersEnabled val requestedInitialKey = params.requestedInitialKey @@ -66,11 +107,24 @@ open class BaseItemKeyedDatasource: ItemKeyedDataSource + */ private fun getSubList(startPosition: Int, defaultLoadSize: Int): List { if(startPosition >= datas.size){ return datas.subList(datas.size - 1, datas.size - 1) diff --git a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/BasePositionalDatasource.kt b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/BasePositionalDatasource.kt index 06070dc..53d3dff 100644 --- a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/BasePositionalDatasource.kt +++ b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/BasePositionalDatasource.kt @@ -1,14 +1,42 @@ +/** + * Copyright (C) 2019 Sysdata S.p.a. + * + * 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. + */ package it.sysdata.ktandroidarchitecturecore import androidx.paging.PositionalDataSource - +/** + * A simple implementation of [PositionalDataSource] + * + * @param Data : the type of data given by the DataSource + * @property defaultLoadSize Int?, default size of a page + * @property datas List, initial dataset + * @property currentPosition Int, position of the first item we want + */ open class BasePositionalDatasource: PositionalDataSource(){ private var defaultLoadSize: Int? = null private lateinit var datas: List private var currentPosition: Int = 0 + /** + * This method returns the datas in a given range of positions + * + * @param params LoadRangeParams + * @param callback LoadRangeCallback + */ override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback) { val loadSize = params.loadSize val startPosition = params.startPosition @@ -22,6 +50,12 @@ open class BasePositionalDatasource: PositionalDataSource(){ callback.onResult(subList) } + /** + * This method loads the initial datas + * + * @param params LoadInitialParams + * @param callback LoadInitialCallback + */ override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback) { var startPosition = params.requestedStartPosition var pageSize = params.pageSize @@ -43,6 +77,13 @@ open class BasePositionalDatasource: PositionalDataSource(){ } } + /** + * returns a sublist of the dataset + * + * @param startPosition Int + * @param defaultLoadSize Int + * @return List + */ private fun getSubList(startPosition: Int, defaultLoadSize: Int): List { if(startPosition >= datas.size){ return datas.subList(datas.size - 1, datas.size - 1) diff --git a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/DataSourceChannel.kt b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/DataSourceChannel.kt index 29ccff6..a1618aa 100644 --- a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/DataSourceChannel.kt +++ b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/interactor/DataSourceChannel.kt @@ -47,7 +47,6 @@ class DataSourceChannel: Channel>(){ val dataSourceBase = dataSource this.liveData = initLiveData(dataSource, pageSize, initialLoadSizeHint, placeHolderEnabled) if (datas != null && datas.isNotEmpty()) { - // TODO: check this if (dataSourceBase is BasePositionalDatasource) { dataSourceBase.init(datas, pageSize) } else if(dataSourceBase is BaseItemKeyedDatasource){ From 8a901d6224538de6d8c06d1fe2d1aef590e47619 Mon Sep 17 00:00:00 2001 From: Salvatore Ranieri Date: Thu, 13 Jun 2019 12:34:53 +0200 Subject: [PATCH 09/10] added copyright and comments --- .../kt/ktandroidarchitecture/DIUtils.kt | 15 ++++++++++ .../ktandroidarchitecture/MainApplication.kt | 15 ++++++++++ .../MainApplicationConfig.kt | 15 ++++++++++ .../repository/AuthRepository.kt | 18 ++++++++++++ .../repository/model/UIUserLogged.kt | 15 ++++++++++ .../repository/model/UserLogged.kt | 15 ++++++++++ .../ktandroidarchitecture/ui/LoginActivity.kt | 28 +++++++++++++++++++ .../kt/ktandroidarchitecture/ui/Note.kt | 24 ++++++++++++++++ .../ui/NoteDataSource.kt | 18 ++++++++++++ .../ui/PagedListAdapterImpl.kt | 21 ++++++++++++++ .../ui/TestDataSource.kt | 20 +++++++++++++ .../usecase/LoginUseCase.kt | 18 ++++++++++++ .../ktandroidarchitecture/usecase/Params.kt | 15 ++++++++++ .../viewmodel/LoginViewModel.kt | 19 ++++++++++++- .../BasePositionalDatasource.kt | 2 +- 15 files changed, 256 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/DIUtils.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/DIUtils.kt index 9f14c30..9073e8e 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/DIUtils.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/DIUtils.kt @@ -1,3 +1,18 @@ +/** + * Copyright (C) 2019 Sysdata S.p.a. + * + * 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. + */ package com.sysdata.kt.ktandroidarchitecture import com.sysdata.kt.ktandroidarchitecture.ui.Note diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/MainApplication.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/MainApplication.kt index 0657436..08e8c96 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/MainApplication.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/MainApplication.kt @@ -1,3 +1,18 @@ +/** + * Copyright (C) 2019 Sysdata S.p.a. + * + * 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. + */ package com.sysdata.kt.ktandroidarchitecture import android.app.Application diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/MainApplicationConfig.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/MainApplicationConfig.kt index 9893fcc..33bee5f 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/MainApplicationConfig.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/MainApplicationConfig.kt @@ -1,3 +1,18 @@ +/** + * Copyright (C) 2019 Sysdata S.p.a. + * + * 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. + */ package com.sysdata.kt.ktandroidarchitecture class MainApplicationConfig private constructor() { diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/repository/AuthRepository.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/repository/AuthRepository.kt index ce8f808..8640fe8 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/repository/AuthRepository.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/repository/AuthRepository.kt @@ -1,3 +1,18 @@ +/** + * Copyright (C) 2019 Sysdata S.p.a. + * + * 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. + */ package com.sysdata.kt.ktandroidarchitecture.repository import com.sysdata.kt.ktandroidarchitecture.repository.model.UserLogged @@ -5,6 +20,9 @@ import it.sysdata.ktandroidarchitecturecore.BaseRepository import it.sysdata.ktandroidarchitecturecore.exception.Failure import it.sysdata.ktandroidarchitecturecore.functional.Either +/** + * Mock implementation of a repository + */ class AuthRepository:BaseRepository() { private object Holder { diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/repository/model/UIUserLogged.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/repository/model/UIUserLogged.kt index 523edac..0f3d9fc 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/repository/model/UIUserLogged.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/repository/model/UIUserLogged.kt @@ -1,3 +1,18 @@ +/** + * Copyright (C) 2019 Sysdata S.p.a. + * + * 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. + */ package com.sysdata.kt.ktandroidarchitecture.repository.model diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/repository/model/UserLogged.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/repository/model/UserLogged.kt index 7de5764..3d6dd5b 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/repository/model/UserLogged.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/repository/model/UserLogged.kt @@ -1,3 +1,18 @@ +/** + * Copyright (C) 2019 Sysdata S.p.a. + * + * 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. + */ package com.sysdata.kt.ktandroidarchitecture.repository.model diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt index d323a0f..14ea2f8 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/LoginActivity.kt @@ -1,3 +1,18 @@ +/** + * Copyright (C) 2019 Sysdata S.p.a. + * + * 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. + */ package com.sysdata.kt.ktandroidarchitecture.ui import android.os.Bundle @@ -40,8 +55,10 @@ class LoginActivity : FragmentActivity(), View.OnClickListener, TextWatcher { viewModel?.actionLogin?.observe(this, ::onUserLoggged) viewModel?.actionLogin?.observeFailure(this, ::onLoginFailed) + // initalization of the datasource channel only with the page size because we use a test datasource that don't need initial datas viewModel?.channelNotes?.initDatasource(pageSize = 10) + // init of the adapter with a click listener for the items adapter = PagedListAdapterImpl { viewModel?.channelPostNotes?.postData(it) } @@ -49,14 +66,25 @@ class LoginActivity : FragmentActivity(), View.OnClickListener, TextWatcher { recycler_view.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false) recycler_view.adapter = adapter + // we observe channel notes to have the updates from the adapter that sends the datas through livedata viewModel?.channelNotes?.observe(this,::onPostNote) + // we observe a general channel used to send datas not related to the adapter viewModel?.channelPostNotes?.observe(this, ::onReceivePost) } + /** + * This method recieves the datas from the channel not related to the adapter of the paged list + * @param note Note? + */ private fun onReceivePost(note: Note?) { Toast.makeText(this, "note : $note", Toast.LENGTH_SHORT).show() } + /** + * this method update the adapter with the the list recieved by the livedata + * + * @param list PagedList? + */ private fun onPostNote(list: PagedList?) { list?.let { adapter?.submitList(list) diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/Note.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/Note.kt index abe2a7f..0d43141 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/Note.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/Note.kt @@ -1,8 +1,32 @@ +/** + * Copyright (C) 2019 Sysdata S.p.a. + * + * 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. + */ package com.sysdata.kt.ktandroidarchitecture.ui import androidx.recyclerview.widget.DiffUtil import java.util.* +/** + * Data object used into the paged lisi adapter, we implement a [diff callback][DiffUtil.ItemCallback] because is need by the adapter + * + * @property index Int + * @property noteId String + * @property title String + * @property content String + * @constructor + */ data class Note(val index:Int, val noteId: String = UUID.randomUUID().toString()) { companion object { val DiffCallback = object : DiffUtil.ItemCallback() { diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/NoteDataSource.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/NoteDataSource.kt index 95f64e5..b9ed5c2 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/NoteDataSource.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/NoteDataSource.kt @@ -1,5 +1,23 @@ +/** + * Copyright (C) 2019 Sysdata S.p.a. + * + * 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. + */ package com.sysdata.kt.ktandroidarchitecture.ui import it.sysdata.ktandroidarchitecturecore.BasePositionalDatasource +/** + * Implementation of [BasePositionalDatasource] with notes + */ class NoteDataSource: BasePositionalDatasource() \ No newline at end of file diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/PagedListAdapterImpl.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/PagedListAdapterImpl.kt index f80f677..d437876 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/PagedListAdapterImpl.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/PagedListAdapterImpl.kt @@ -1,3 +1,18 @@ +/** + * Copyright (C) 2019 Sysdata S.p.a. + * + * 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. + */ package com.sysdata.kt.ktandroidarchitecture.ui import android.util.Log @@ -9,6 +24,12 @@ import androidx.paging.PagedListAdapter import androidx.recyclerview.widget.RecyclerView import com.sysdata.kt.ktandroidarchitecture.R +/** + * Dummy implementation of [PagedListAdapter] + * + * @property onClick Function1 + * @constructor + */ class PagedListAdapterImpl(val onClick: (Note) -> Unit) : PagedListAdapter(Note.DiffCallback) { class ListItemViewHolder(val view: View): RecyclerView.ViewHolder(view) { var note: Note? = null diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/TestDataSource.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/TestDataSource.kt index 80149a7..9f895ed 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/TestDataSource.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/ui/TestDataSource.kt @@ -1,7 +1,27 @@ +/** + * Copyright (C) 2019 Sysdata S.p.a. + * + * 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. + */ package com.sysdata.kt.ktandroidarchitecture.ui import androidx.paging.ItemKeyedDataSource +/** + * Fake datasource that returns random data on each call + * + * @property datas List + */ class TestDataSource: ItemKeyedDataSource(){ private val datas = listOf(Note(1), Note(2), Note(3), Note(4), Note(5)) diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/usecase/LoginUseCase.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/usecase/LoginUseCase.kt index bda8315..f93950f 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/usecase/LoginUseCase.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/usecase/LoginUseCase.kt @@ -1,3 +1,18 @@ +/** + * Copyright (C) 2019 Sysdata S.p.a. + * + * 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. + */ package com.sysdata.kt.ktandroidarchitecture.usecase import com.sysdata.kt.ktandroidarchitecture.repository.AuthRepository @@ -6,6 +21,9 @@ import it.sysdata.ktandroidarchitecturecore.exception.Failure import it.sysdata.ktandroidarchitecturecore.functional.Either import it.sysdata.ktandroidarchitecturecore.interactor.UseCase +/** + * Fake login use case that calls a mock repository + */ class LoginUseCase: UseCase() { override suspend fun run(params: LoginActionParams): Either { return AuthRepository.instance.login(params.email, params.password) diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/usecase/Params.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/usecase/Params.kt index 4363f5d..73d1bc1 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/usecase/Params.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/usecase/Params.kt @@ -1,3 +1,18 @@ +/** + * Copyright (C) 2019 Sysdata S.p.a. + * + * 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. + */ package com.sysdata.kt.ktandroidarchitecture.usecase import it.sysdata.ktandroidarchitecturecore.interactor.ActionParams diff --git a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/viewmodel/LoginViewModel.kt b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/viewmodel/LoginViewModel.kt index 122489c..0b5a34c 100644 --- a/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/viewmodel/LoginViewModel.kt +++ b/app/src/main/java/com/sysdata/kt/ktandroidarchitecture/viewmodel/LoginViewModel.kt @@ -1,10 +1,24 @@ +/** + * Copyright (C) 2019 Sysdata S.p.a. + * + * 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. + */ package com.sysdata.kt.ktandroidarchitecture.viewmodel import com.sysdata.kt.ktandroidarchitecture.DIUtils import com.sysdata.kt.ktandroidarchitecture.repository.model.UIUserLogged import com.sysdata.kt.ktandroidarchitecture.repository.model.UserLogged import com.sysdata.kt.ktandroidarchitecture.ui.Note -import com.sysdata.kt.ktandroidarchitecture.ui.NoteDataSource import com.sysdata.kt.ktandroidarchitecture.ui.TestDataSource import com.sysdata.kt.ktandroidarchitecture.usecase.LoginActionParams import com.sysdata.kt.ktandroidarchitecture.usecase.LoginUseCase @@ -13,13 +27,16 @@ import it.sysdata.ktandroidarchitecturecore.platform.BaseViewModel class LoginViewModel: BaseViewModel() { + //action to launch a usecase that simulate a login val actionLogin = Action.Builder() .useCase(LoginUseCase::class.java) .buildWithUiModel { UIUserLogged(it.username) } + // definition of the datasource channel, used by the paged list val channelNotes = DataSourceChannel.Builder() .dataSource(TestDataSource::class.java) .build() + // base channel used to post and recieve datas val channelPostNotes = DIUtils.channel } \ No newline at end of file diff --git a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/BasePositionalDatasource.kt b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/BasePositionalDatasource.kt index 53d3dff..060d103 100644 --- a/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/BasePositionalDatasource.kt +++ b/ktandroidarchitecturecore/src/main/java/it/sysdata/ktandroidarchitecturecore/BasePositionalDatasource.kt @@ -33,7 +33,7 @@ open class BasePositionalDatasource: PositionalDataSource(){ /** * This method returns the datas in a given range of positions - * + * * @param params LoadRangeParams * @param callback LoadRangeCallback */ From eea3609db0e3e9e0fda80ac58f3f0a67d29388d9 Mon Sep 17 00:00:00 2001 From: Salvatore Ranieri Date: Fri, 14 Jun 2019 09:08:40 +0200 Subject: [PATCH 10/10] updated readme --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 8a43866..0f26e25 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,6 @@ A Kotlin android architecture with Google Architecture Components ## 1. A Brief Introduciton The app is a sample project that shows how to implement the KTAndroidArchitecture into your Android app. -<<<<<<< HEAD CHANGELOG: 1.0.1 @@ -13,8 +12,6 @@ CHANGELOG: - fixed the behavior of the error post in the observeFailure function. - Updated Gradle plugin version. -======= ->>>>>>> 707078fb6d64d589a192b93396f8080a41183eac ### 1.1 What is KTAndroidArchitecture? It is a layer-based architecture that allows a real disentangle of the UI components from the business logic.