Skip to content

Instantly share code, notes, and snippets.

@nawanirakshit
Created January 18, 2020 05:57
Show Gist options
  • Save nawanirakshit/11713f26e2e93d68d14d6b15058297a2 to your computer and use it in GitHub Desktop.
Save nawanirakshit/11713f26e2e93d68d14d6b15058297a2 to your computer and use it in GitHub Desktop.
Base/Core class for Android Developement
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:bind="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="viewModel"
type="package_name.DashboardViewModel" />
</data>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_dashboard"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:adapter="@{viewModel.adapter}"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</layout>
/**
* Created By: Rakshit Nawani
* Date: January 18 2020
*
* BaseRecyclerViewAdapter can be used as a base class for all the Recycler View's Adapter, it contains all the basic functions needed by the user, like
* 1. Add Item
* 2. Update Item
* 3. Add List
* 4. Remove Item
* and many more according to needs.
*
*/
abstract class BaseRecyclerViewAdapter<BD : ViewDataBinding, T>(
@LayoutRes private var layoutId: Int, var mList: ArrayList<T> = ArrayList()
) :
RecyclerView.Adapter<BaseRecyclerViewAdapter<BD, T>.BaseRecyclerViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder =
BaseRecyclerViewHolder(
DataBindingUtil.inflate(
LayoutInflater.from(parent.context),
layoutId,
parent,
false
)
)
private var baseRecyclerViewItemListener: BaseRecyclerViewItemListener? = null
fun addItem(t: T, position: Int? = null) {
when (position) {
null -> mList.add(t)
else -> mList.add(position, t)
}
notifyItemInserted(position ?: mList.size - 1)
baseRecyclerViewItemListener?.addItem(position ?: mList.size - 1)
}
open fun addItemAtBeginning(t: T) {
mList.add(0, t)
notifyItemInserted(0)
}
open fun getItem(position: Int): T = mList[position]
fun findItem(predicate: (T) -> Boolean): T? = mList.find(predicate)
fun itemPosition(t: T): Int = mList.indexOf(t)
open fun removeItem(position: Int) {
if (position < 0) return
mList.removeAt(position)
notifyItemRemoved(position)
baseRecyclerViewItemListener?.removeItem(position)
}
fun updateItem(position: Int, t: T) {
mList[position] = t
notifyItemChanged(position)
baseRecyclerViewItemListener?.changeItem(position)
}
fun addItems(t: List<T>) {
mList.addAll(t)
notifyDataSetChanged()
baseRecyclerViewItemListener?.addAllItems()
}
override fun getItemCount(): Int = mList.size
fun getAllItems(): ArrayList<T> = mList
open fun clear() {
mList.clear()
notifyDataSetChanged()
}
operator fun contains(item: T): Boolean = mList.contains(item)
fun getPositionForItem(item: T) = when {
mList.size > 0 -> mList.indexOf(item)
else -> -1
}
fun moveItems(fromPosition: Int, toPosition: Int): Boolean {
if (fromPosition < toPosition) {
for (i in fromPosition until toPosition) {
Collections.swap(mList, i, i + 1)
}
} else {
for (i in fromPosition downTo toPosition + 1) {
Collections.swap(mList, i, i - 1)
}
}
notifyItemMoved(fromPosition, toPosition)
return true
}
inner class BaseRecyclerViewHolder(var binding: BD) : RecyclerView.ViewHolder(binding.root)
}
/**
* Created By: Rakshit Nawani
* Date: January 18 2020
*
* Binding Activity can be used as a base class for all the activity, it contains all the basic functions needed by the user, like
* 1. Printing log
* 2. Displaying Toast
* 3. Show/Hide Loading
* and many more according to needs.
*
* In an Activity extend it with BindingActivity<Data Binding Class of that class>
* After extending Activity we need to override methods which is getLayoutResId, implement it like below
*
* @LayoutRes
* override fun getLayoutResId() = R.layout.your_layout_name_here
*
*
*/
abstract class BindingActivity<T : ViewDataBinding> : AppCompatActivity() {
@LayoutRes
abstract fun getLayoutResId(): Int
private var loadingDialog: AlertDialog? = null
protected lateinit var binding: T private set
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//Printling the Class name in logs
printLog(javaClass.simpleName)
binding = DataBindingUtil.setContentView(this, getLayoutResId())
}
private var toast: Toast? = null
/**
* showToast with message
* @view: for custom toast provide view perform inflater and other task at your end
* @gravity: provide gravity
*/
fun showToast(
message: String?,
view: View? = null,
duration: Int = Toast.LENGTH_LONG,
gravity: Int = Gravity.BOTTOM or Gravity.CENTER_VERTICAL, @DimenRes x: Int = 0, @DimenRes y: Int = 0,
cancelPrevious: Boolean = false
) {
if (cancelPrevious) toast?.cancel()
// set custom view
when {
view != null -> {
toast = Toast(context)
toast?.view = view
}
else -> toast = Toast.makeText(context, message, duration)
}
// set duration
toast?.duration = duration
// set position
var marginY = 0
var marginX = 0
if (y != 0) marginY = resources.getDimensionPixelSize(y)
if (x != 0) marginX = resources.getDimensionPixelSize(x)
if (marginX > 0 || marginY > 0) toast?.setGravity(gravity, marginX, marginY)
// show toast
toast?.show()
}
/**
* For Displaying the loading when an API is hit
*/
fun showLoading(context: Context) {
try {
if (loadingDialog == null) {
val factory: LayoutInflater = LayoutInflater.from(context)
val deleteDialogView: View = factory.inflate(R.layout.loading_screen, null)
loadingDialog =
AlertDialog.Builder(context, R.style.AppCompatAlertDialogStyle).create()
loadingDialog!!.setView(deleteDialogView)
loadingDialog!!.setCanceledOnTouchOutside(false)
loadingDialog!!.setCancelable(false)
hideKeyboard()
}
loadingDialog!!.show()
} catch (e: Exception) {
e.printStackTrace()
}
}
/**
* For hiding the loading
*/
open fun hideLoading() {
try {
loadingDialog?.dismiss()
hideKeyboard()
} catch (e: Exception) {
e.printStackTrace()
}
}
/**
* For Hiding the keyboard
*/
open fun hideKeyboard() {
val view = this.currentFocus
if (view != null) {
val imm =
(getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager)
imm.hideSoftInputFromWindow(view.windowToken, 0)
}
}
/**
* function to check if internet connection is active or not.
*
* @return true if connected to internet else false
*/
open fun isConnectedToInternet(): Boolean {
val cm =
(getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager)
val activeNetwork = cm.activeNetworkInfo
return activeNetwork != null
}
open fun printLog(message: String) {
Log.d(getString(R.string.app_name), message)
}
}
/**
* Created By: Rakshit Nawani
* Date: January 18 2020
*
* BindingFragment can be used as a base class for all the Fragments, it contains all the basic functions needed by the user
* which will be connected with the BindingActivity
*
* In a Fragment extend it with BindingFragment<Data Binding Class of that class>
* After extending Fragment we need to override methods which is getLayoutResId, implement it like below
*
* @LayoutRes
* override fun getLayoutResId() = R.layout.your_layout_name_here
*/
abstract class BindingFragment<T : ViewDataBinding> : Fragment() {
@LayoutRes
abstract fun getLayoutResId(): Int
private var loadingDialog: AlertDialog? = null
protected lateinit var binding: T private set
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
(activity as BindingActivity<*>).printLog(javaClass.simpleName)
setHasOptionsMenu(true)
return DataBindingUtil.inflate<T>(inflater, getLayoutResId(), container, false)
.apply { binding = this }.root
}
private var toast: Toast? = null
/**
* showToast with message
* @view: for custom toast provide view perform inflater and other task at your end
* @gravity: provide gravity
*/
open fun showToast(
message: String?,
view: View? = null,
duration: Int = Toast.LENGTH_LONG,
gravity: Int = Gravity.BOTTOM or Gravity.CENTER_VERTICAL, @DimenRes x: Int = 0, @DimenRes y: Int = 0,
cancelPrevious: Boolean = false
) {
(activity as BindingActivity<*>).showToast(
message = message,
view = view,
duration = duration,
gravity = gravity,
cancelPrevious = cancelPrevious
)
}
/**
* For Displaying the loader
*/
fun showLoading(context: Context) {
try {
(activity as BindingActivity<*>).hideLoading()
(activity as BindingActivity<*>).showLoading(context)
} catch (e: Exception) {
e.printStackTrace()
}
}
/**
* For hiding the loading
*/
fun hideLoading() {
(activity as BindingActivity<*>).hideLoading()
}
}
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="data"
type="String" />
</data>
<TextView
android:text="@{data}"
android:id="@+id/tv_hospital_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/divider_dark" />
</layout>
/**
* Created By: Rakshit Nawani
* Date: January 18 2020
*
* Sample Activity, displays how to use the Base Classes
*
*/
class DashboardActivity : BindingActivity<ActivityDashboardBinding>() {
@LayoutRes
override fun getLayoutResId() = R.layout.activity_dashboard
lateinit var viewModel: DashboardViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//Attaching View Model
viewModel = DashboardViewModel()
binding.viewModel = viewModel
binding.lifecycleOwner = this
//Adding click Listeners for the adapter's item
viewModel.adapter.listener = object : DashboardAdapter.DataListListener {
override fun itemClick(data: String) {
//Calling a function from Base Class
printlog(data)
}
}
}
}
/**
* Created By: Rakshit Nawani
* Date: January 18 2020
*
* Recycler View's Adapter class extending BaseRecyclerViewAdapter<Data_Binding_Class, Model_Type>
*
*/
class DashboardAdapter: BaseRecyclerViewAdapter<DashboardListItemBinding, String>(R.layout.dashboard_list_item) {
override fun onBindViewHolder(holder: BaseRecyclerViewHolder, position: Int) {
holder.binding.data = getItem(position)
holder.binding.root.setOnClickListener {
listener?.itemClick(getItem(holder.adapterPosition))
}
}
var listener: DataListListener? = null
interface DataListListener {
fun itemClick(data: String)
}
}
/**
* Created By: Rakshit Nawani
* Date: January 18 2020
*
* View Model class for DashboardActivity.kt extending BaseViewModel a core class
*
* Displaying how to Add a recycler View Adapter in a View model
*/
class DashboardViewModel: BaseViewModel() {
val adapter = DashboardAdapter()
init{
// Add data in your Adapter
val list = arrayListOf<String>()
list.add("A")
list.add("B")
list.add("C")
list.add("D")
list.add("E")
adapter.addItems(list)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment