Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save yogithesymbian/b476ef3640cb4f1343ef3816064be8be to your computer and use it in GitHub Desktop.
Save yogithesymbian/b476ef3640cb4f1343ef3816064be8be to your computer and use it in GitHub Desktop.
Kotlin Template Generator StarterPackJelly 2021-2022 - [![License](https://poser.pugx.org/laravel/lumen-framework/license.svg)](https://github.com/yogithesymbian) crud + infinite pagination
plugins {
id 'com.android.application'
id 'kotlin-android'
}
apply plugin: 'com.google.gms.google-services'
apply plugin: 'kotlin-parcelize'
android {
// lintOptions {
// checkReleaseBuilds false
// // Or, if you prefer, you can continue to check for errors in release builds,
// // but continue the build even when errors are found:
// // Turns off checks for the issue IDs you specify.
// disable 'TypographyFractions', 'TypographyQuotes'
// // Turns on checks for the issue IDs you specify. These checks are in
// // addition to the default lint checks.
// enable 'RtlHardcoded', 'RtlCompat', 'RtlEnabled'
// // To enable checks for only a subset of issue IDs and ignore all others,
// // list the issue IDs with the 'check' property instead. This property overrides
// // any issue IDs you enable or disable using the properties above.
// check 'NewApi', 'HandlerLeak'
// // If set to true, turns off analysis progress reporting by lint.
// quiet true
// // if set to true (default), stops the build if errors are found.
// abortOnError false
// // if true, only report errors.
// ignoreWarnings true
// baseline file("lint-baseline.xml")
// }
compileSdk 31
defaultConfig {
applicationId "id.scodeid.kotlin_setup_starterpackjelly2021"
minSdk 18
targetSdk 31
versionCode 1
versionName "1.0"
//
buildConfigField "String", "BASE_URL", '"http://192.168.216.190:3001/"'
// buildConfigField "String", "BASE_URL_ONLINE", '"http://47.254.248.35/api/api-remote-login-apps/public/"'
// buildConfigField "String", "API_TOKEN", '"bearer NExsTm5WT29zZ0RCczRoMkFuVnFJNHVVM3VLaFNERkJuWU9acUpOaA=="'
multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
viewBinding true
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
implementation "androidx.fragment:fragment-ktx:1.3.6"
implementation "androidx.activity:activity-ktx:1.3.1"
implementation 'androidx.multidex:multidex:2.0.1'
/**
* FAN ( Fast Android Networking )
*/
implementation 'com.amitshekhar.android:android-networking:1.0.2'
implementation 'com.amitshekhar.android:rx2-android-networking:1.0.2'
/**
* Architecture Component
* LifeCycle Component
*/
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.annotation:annotation:1.2.0'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
implementation 'androidx.work:work-runtime-ktx:2.7.0'
implementation 'com.google.android.gms:play-services-base:17.6.0'
androidTestImplementation "androidx.arch.core:core-testing:2.1.0"
//gson
implementation 'com.google.code.gson:gson:2.8.8'
implementation "androidx.browser:browser:1.3.0"
// firebase
implementation platform('com.google.firebase:firebase-bom:28.4.2')
implementation 'com.google.firebase:firebase-analytics-ktx'
// Declare the dependencies for the Firebase Cloud Messaging and Analytics libraries
// When using the BoM, you don't specify versions in Firebase library dependencies
implementation 'com.google.firebase:firebase-messaging-ktx'
}
// https://github.com/yogithesymbian/Kotlin-Setup-Starterpackjelly-2021
// model viemodel viewmodelfacotry interface livedata
// soon will publish
// (File Header.java)
/**
* Android Studio Arctic Fox | 2020.3.1 Patch 3
* Build #AI-203.7717.56.2031.7784292, built on October 1, 2021
* Runtime version: 11.0.10+0-b96-7281165 x86_64
* VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
* macOS 11.6
* GC: G1 Young Generation, G1 Old Generation
* Memory: 2048M
* Cores: 8
* Registry: external.system.auto.import.disabled=true, ide.balloon.shadow.size=0
* Non-Bundled Plugins: com.mallowigi, com.robohorse.robopojogenerator, dev.polek.adbwifi, Dart, com.thoughtworks.gauge, org.jetbrains.kotlin, io.flutter, com.chrisrm.idea.MaterialThemeUI, org.intellij.plugins.markdown
* -----------------------------------
* \ ^__^
* \ (oo)\_______
* (__)\ )\/\
* ||----w |
* || ||
* git clone https://github.com/yogithesymbian/Kotlin-Setup-Starterpackjelly-2021/tree/master
* 2021 - 2022 (C) Yogi Arif Widodo (yogithesymbian)
*/
fragmentactivity
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME}#end
import android.annotation.SuppressLint
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.RecyclerView
import id.scode.kuisioner.R
import id.scode.kuisioner.utils.gone
import id.scode.kuisioner.utils.visible
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlin.properties.Delegates
import kotlinx.coroutines.*
import gone
import visible
#parse("File Header.java")
class ${NAME} : Fragment(), $View_Interface_Class {
private lateinit var binding: ${Item_Layout_ID_Binding}Binding
private val observer =
Observer<MutableList<${Model_Class}>> { item ->
if (item != null)
scoreAdapter.setData(item)
binding.$ProgressBar?.gone()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
page$Adapter_Class = 0
totalPage$Adapter_Class = 0
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = ${Item_Layout_ID_Binding}Binding.inflate(inflater, container, false)
GlobalScope.launch {
show$View_Model_Class()
}
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
scoreAdapter = $Adapter_Class(mutableList) {
Log.d(TAG_LOG,"clicked ${it.soal}")
//try {
// val intent = Intent(requireContext(), ScoreDetailActivity::class.java)
// intent.putExtra(ScoreDetailActivity.EXTRA_SCORE_DATA, it)
// requireContext().startActivity(intent)
//} catch (e: Exception) {
// Log.d(TAG_LOG, "clicked $e")
//}
}
initListener$Adapter_Class()
}
private fun initListener$Adapter_Class() {
binding.$Id_Recycler
.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
val linearLayoutManager = recyclerView.layoutManager as LinearLayoutManager
val countItem = linearLayoutManager.itemCount
val lastVisiblePosition =
linearLayoutManager.findLastCompletelyVisibleItemPosition()
val isLastPosition = countItem.minus(1) == lastVisiblePosition
if (isLastPosition && page$Adapter_Class < totalPage$Adapter_Class) {
page$Adapter_Class = page$Adapter_Class .plus(1)
val viewModel: $View_Model_Class by viewModels { $View_Model_Factory_Class(this@HomeFragment) }
Log.e(TAG_LOG, "page : $page$Adapter_Class")
viewModel.show$View_Model_Class(requireContext(), page$Adapter_Class .toString())
}
}
})
}
private suspend fun show$View_Model_Class() {
try{
// get history absen where no expired date
withContext(Dispatchers.Main) {
scoreAdapter.notifyDataSetChanged()
binding.$Id_Recycler .itemAnimator = DefaultItemAnimator()
binding.$Id_Recycler .setHasFixedSize(true)
binding.$Id_Recycler .layoutManager = LinearLayoutManager(requireContext())
binding.$Id_Recycler .adapter = scoreAdapter
}
val viewModel: $View_Model_Class by viewModels { $View_Model_Factory_Class(this) }
withContext(Dispatchers.Main) {
viewModel.liveData().observe(viewLifecycleOwner, observer)
Log.e(TAG_LOG, "page : $page$Adapter_Class")
if (scoreAdapter.itemCount == 0)
viewModel.show$View_Model_Class(requireContext(), page$Adapter_Class .toString())
}
} catch (e: Exception){
Log.d(TAG_LOG, "exception request ${e.printStackTrace()}")
}
}
override fun showLoading$View_Interface_Class() {
binding.$ProgressBar?.visible()
}
override fun hideLoading$View_Interface_Class() {
binding.$ProgressBar?.gone()
}
override fun paginationTotalPage$View_Interface_Class(totalPageDef: Int) {
totalPage$Adapter_Class = totalPageDef
}
// override fun show$View_Interface_Class(data: MutableList<${Model_Class}>?) {
// GlobalScope.launch {
// mutableList.clear()
// val assign = async {
// data?.let {
// mutableList.addAll(it)
// }
// }
// assign.await()
// }
//}
companion object {
val TAG_LOG = ${NAME}::class.java.simpleName
lateinit var scoreAdapter: $Adapter_Class
private var mutableList: MutableList<${Model_Class}> = mutableListOf()
// pagination
private var page$Adapter_Class by Delegates.notNull<Int>()
private var totalPage$Adapter_Class by Delegates.notNull<Int>()
}
}
// View_Interface_Class
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME}#end
#parse("File Header.java")
interface ${NAME} {
fun showLoading${NAME}()
fun hideLoading${NAME}()
fun paginationTotalPage${NAME}(totalPageDef: Int)
// fun show${NAME}(
// data: MutableList<${Model_Class}>
//)
//fun showSingle${NAME}(
// data: ${Model_Class}
//)
}
// ViewModel
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME}#end
import android.content.Context
import android.util.Log
import android.widget.Toast
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.androidnetworking.AndroidNetworking
import com.androidnetworking.common.Priority
import com.androidnetworking.error.ANError
import com.androidnetworking.interfaces.JSONObjectRequestListener
import org.json.JSONObject
import com.google.gson.Gson
import kotlinx.coroutines.*
import org.json.JSONObject
#parse("File Header.java")
class ${NAME}(val view: $viewinterface) : ViewModel() {
val mutableLiveData = MutableLiveData<MutableList<${Model_Class}>>()
// val mutableLiveDataSingle = MutableLiveData<${Model_Class}?>()
companion object {
val TAG_LOG: String = ${NAME}::class.java.simpleName
private var mutableList: MutableList<${Model_Class}> = mutableListOf()
// private var mutableListSingle: ${Model_Class}? = null
}
fun show${NAME}(
context: Context,
page: String
) {
view.showLoading()
val gson = Gson()
Log.d(
TAG_LOG, """
request api is in background
server : $Class_EndPoint_And_Url
""".trimIndent()
)
AndroidNetworking.$getOrPost($Class_EndPoint_And_Url)
.addHeaders("Authorization", "${BuildConfig.API_TOKEN}")
.addQueryParameter("page", page)
.addQueryParameter("size", "5")
//.addBodyParameter("password", pass)
.setPriority(Priority.LOW)
.build()
.getAsJSONObject(object : JSONObjectRequestListener {
override fun onResponse(response: JSONObject) {
GlobalScope.launch {
val jsonArrayData = async { response.toString() }
val responseJson = async {
gson.fromJson(
jsonArrayData.await(),
${Model_Class_Response}::class.java
)
}
Log.d(TAG_LOG, """ ------
response ${responseJson.await()}
""".trimIndent())
val data = responseJson.await()?.results
data?.let {
// view.show$viewinterface(data)
mutableLiveData.postValue(it)
}
withContext(Dispatchers.Main) {
view.hideLoading()
Toast.makeText(context,"${toast_message}", Toast.LENGTH_LONG).show()
}
mutableLiveData.postValue(data)
view.paginationTotalPage$View_Interface_Class(response.optInt("total_pages"))
}
}
override fun onError(anError: ANError) {
if (anError.errorCode != 0) {
Log.d( TAG_LOG, "onError errorCode : ${anError.errorCode}")
Log.d( TAG_LOG, "onError errorBody : ${anError.errorBody}")
Log.d(TAG_LOG, "onError errorDetail : ${anError.errorDetail}")
if (anError.errorCode == "404".toInt())
mutableList.clear()
mutableLiveData.postValue(mutableList)
// if (anError?.errorCode == "404".toInt())
// mutableListSingle = null
// mutableLiveDataSingle.postValue(mutableListSingle)
} else {
Log.d( TAG_LOG, "onError errorDetail : " + anError.errorDetail)
}
}
})
}
fun liveData(): LiveData<MutableList<${Model_Class}>> {
return mutableLiveData
}
// fun liveDataSingle(): LiveData<${Model_Class}?> {
// return mutableLiveDataSingle
// }
}
// View_Model_Factory_Class
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME}#end
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
#parse("File Header.java")
class ${NAME}(private val view: $viewinterface) :
ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return ${viewinterface}Model(view) as T
}
}
// RecyclerView | Adapter
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME}#end
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.extensions.LayoutContainer
#parse("File Header.java")
class ${NAME} (
private val items: MutableList<${Model_Class}>,
private val listener: (${Model_Class}) -> Unit
) : RecyclerView.Adapter<${NAME}.${ViewHolder_Class}>(){
init {
setHasStableIds(true)
}
fun setData(itemsData: MutableList<${Model_Class}>) {
// items.clear()
items.addAll(itemsData)
notifyDataSetChanged()
}
class ${ViewHolder_Class}(override val containerView: View): RecyclerView.ViewHolder(containerView),
LayoutContainer {
private val binding = ${Item_Layout_ID_Binding}Binding.bind(containerView)
fun bindItem(item: ${Model_Class}, listener: (${Model_Class}) -> Unit) {
//item.image.let { Picasso.get().load(it).fit().into(img_main) }
with(binding){
// this.txtScore.text = item.score.toString()
containerView.setOnClickListener { listener(item) }
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
${ViewHolder_Class}(LayoutInflater.from(parent.context).inflate(R.layout.${Item_Layout_ID}, parent, false))
override fun getItemCount(): Int = items.size
override fun onBindViewHolder(holder: ${ViewHolder_Class}, position: Int) =
holder.bindItem(items[position], listener)
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getItemViewType(position: Int): Int {
return position
}
companion object{
val TAG_LOG = ${NAME}::class.java.simpleName
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment