Skip to content

Instantly share code, notes, and snippets.

@effe-megna
Created May 15, 2019 07:33
Show Gist options
  • Select an option

  • Save effe-megna/8b6be2b8550052b4cdad3413aa5a4269 to your computer and use it in GitHub Desktop.

Select an option

Save effe-megna/8b6be2b8550052b4cdad3413aa5a4269 to your computer and use it in GitHub Desktop.
package com.bepower.becharge.ui
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.View.OnClickListener
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.bepower.becharge.MainActivity
import com.bepower.becharge.R
import com.bepower.becharge.databinding.ActivityHeaderRowBinding
import com.bepower.becharge.databinding.CardUserActivityBinding
import com.bepower.becharge.databinding.CardUserRateplanBinding
import com.bepower.becharge.databinding.FragmentActivitiesHistoryBinding
import com.bepower.becharge.extensions.AnimationType
import com.bepower.becharge.extensions.tryCatchLifecycleAware
import com.bepower.becharge.net.models.ActivitiesResponse
import com.bepower.becharge.net.models.Activity
import com.bepower.becharge.net.models.ActivityRow
import com.bepower.becharge.net.models.ActivityType
import com.bepower.becharge.viewModels.ActivitiesHistoryViewModel
import jp.wasabeef.recyclerview.animators.SlideInDownAnimator
import kotlinx.android.synthetic.main.fragment_country_selection.*
import kotlinx.coroutines.launch
import kotlin.properties.Delegates
data class ActivityHeader(
val date: String,
val totalEnergy: String
): ActivityRow
class ActivitiesHistoryFragment : BaseFragment() {
val mViewModel: ActivitiesHistoryViewModel by lazy {
constructViewModel(ActivitiesHistoryViewModel(applicationComponent, application))
}
val adapter = ActivitiesAdapter { [email protected](it) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
launch {
initRecyclerView()
}
// init with mock activities ** WORKAROUND **
adapter.activities = mViewModel.generateActivitiesRowFromActivityResponse(ActivitiesResponse(
listOf(
Activity(cp_id = "123", type = ActivityType.recharge, deactivation = true, date = null, description = null, end_date = null, energy = null, evc_address = null, evc_city = null, evc_id = null, invoice_data = null, invoice_pdf = null, payment_status = null, price = null, start_date = null),
Activity(cp_id = "123", type = ActivityType.recharge_outbound, deactivation = true, date = null, description = null, end_date = null, energy = null, evc_address = null, evc_city = null, evc_id = null, invoice_data = null, invoice_pdf = null, payment_status = null, price = null, start_date = null),
Activity(cp_id = "123", type = ActivityType.recharge_inbound, deactivation = true, date = null, description = null, end_date = null, energy = null, evc_address = null, evc_city = null, evc_id = null, invoice_data = null, invoice_pdf = null, payment_status = null, price = null, start_date = null)
),
total_energy = 0f
))
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return FragmentActivitiesHistoryBinding.inflate(LayoutInflater.from(context)).apply {
onLoadMore = [email protected]()
onCloseClick = [email protected]()
footerText = [email protected]
}.apply {
lifecycleOwner = this@ActivitiesHistoryFragment
}.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
interactionListener!!.setTabBarVisibility(false)
recyclerView.apply {
layoutManager = LinearLayoutManager(this.context)
setHasFixedSize(true)
adapter = [email protected]
}
}
private suspend fun initRecyclerView() {
tryCatchLifecycleAware(context, {
(activity as MainActivity).setVisibilityOfIndicator(false)
}) {
(activity as MainActivity).setVisibilityOfIndicator(true)
adapter.activities = mViewModel.loadActivities() ?: return@tryCatchLifecycleAware
}
}
private fun onActivityClick(activityRow: ActivityRow) {
navigationListener!!.pushFragment(
UserActivityFragment.newInstance(activityRow as Activity),
true,
AnimationType.DETAIL
)
}
private fun onLoadMore() = OnClickListener {
launch {
tryCatchLifecycleAware(context, {
(activity as MainActivity).setVisibilityOfIndicator(false)
}) {
(activity as MainActivity).setVisibilityOfIndicator(true)
adapter.activities += mViewModel.loadMore() ?: return@tryCatchLifecycleAware
}
}
}
class ItemWithId<T>(
val id: Int,
val item: T
)
class ActivitiesAdapter(
private val handleActivityClick: (activity: ActivityRow) -> Unit
): RecyclerView.Adapter<ActivitiesAdapter.ViewHolder>(), AutoUpdatableAdapter {
var activities: List<ActivityRow> by Delegates.observable(emptyList()) { _, oldList, newList ->
val oldList = oldList.foldIndexed(emptyList<ItemWithId<ActivityRow>>()) { index, acc, activityRow ->
acc + ItemWithId(index, activityRow)
}
val newList = newList.foldIndexed(emptyList<ItemWithId<ActivityRow>>()) { index, acc, activityRow ->
acc + ItemWithId(index, activityRow)
}
autoNotify(oldList, newList) { o, n ->
o.id == n.id
}
}
inner class ViewHolder(val binding: ViewDataBinding) : RecyclerView.ViewHolder(binding.root)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val layout = when(viewType) {
0 -> R.layout.card_user_rateplan
1 -> R.layout.card_user_activity
2 -> R.layout.activity_header_row
else -> R.layout.card_user_activity
}
val binding = DataBindingUtil.inflate<ViewDataBinding>(
inflater!!,
layout,
parent,
false
)
return ViewHolder(binding)
}
/**
@return
0 -> rateplan card
1 -> recharge card
2 -> header
666 -> skip activity
*/
override fun getItemViewType(position: Int): Int {
return when (val item = activities[position]) {
is Activity -> when (item.type) {
ActivityType.rateplan -> 0
ActivityType.recharge -> 1
ActivityType.recharge_inbound -> 1
ActivityType.recharge_outbound -> 1
else -> 666
}
is ActivityHeader -> 2
else -> 2
}
}
override fun getItemCount(): Int = activities.size
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = activities[position]
val onClick = OnClickListener { handleActivityClick(item) }
when (getItemViewType(position)) {
0 -> {
with (holder.binding as CardUserRateplanBinding) {
this.activity = item as Activity
this.onClick = onClick
}
}
1 -> {
with (holder.binding as CardUserActivityBinding) {
activity = item as Activity
this.onClick = onClick
}
}
2 -> {
with (holder.binding as ActivityHeaderRowBinding) {
this.date = (item as ActivityHeader).date
this.totalEnergy = item.totalEnergy
}
}
}
}
}
companion object {
@JvmStatic
fun newInstance() = ActivitiesHistoryFragment()
}
}
interface AutoUpdatableAdapter {
fun <T> RecyclerView.Adapter<*>.autoNotify(oldList: List<T>, newList: List<T>, compare: (T, T) -> Boolean) {
val diff = DiffUtil.calculateDiff(object : DiffUtil.Callback() {
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return compare(oldList[oldItemPosition], newList[newItemPosition])
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition] == newList[newItemPosition]
}
override fun getOldListSize() = oldList.size
override fun getNewListSize() = newList.size
})
diff.dispatchUpdatesTo(this)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment