I'm assigning a value to lateinit varable in my first function and I want to access same value in my second function but gives me an error UninitializedPropertyAccessException. I know it is because of variable scope. My question is how can i access this value?
Here is my lateinit variables
lateinit var area:String
lateinit var zipcode:String
Here is my first function
fun showSearchDialog(view: View) {
val dialog = context?.let { Dialog(it) }
dialog?.requestWindowFeature(Window.FEATURE_NO_TITLE)
dialog?.setCancelable(true)
dialog?.setContentView(R.layout.alertdialog_search_layout)
//Initializing the views of the dialog.
val postalCode: TextInputEditText? = dialog?.findViewById(R.id.et_zip_code)
val sliderArea: Slider? = dialog?.findViewById(R.id.slider_area)
val searchButton: Button? = dialog?.findViewById(R.id.search_btn)
searchButton?.setOnClickListener {
if (sliderArea != null) {
area = sliderArea.value.toString()
}
zipcode = postalCode?.text.toString()
val postCodeUpperCase = postalCode?.text.toString().toUpperCase(Locale.ROOT)
if (zipcode.isEmpty()) {
postalCode?.error = "Please enter your post code"
postalCode?.requestFocus()
} else if (isValidZipCode(postCodeUpperCase)) {
postalCode?.error = "Please enter valid post code"
postalCode?.requestFocus()
} else {
if (isNetworkAvailable(requireContext())) {
viewModel.getSkipFilterList(zipcode, area)
Toast.makeText(context, "Valid postal code is = $zipcode", Toast.LENGTH_LONG).show()
}
else {
showAlertDialog(getString(R.string.no_internet))
}
}
//dialog.dismiss()
}
dialog?.show()
Here is my second Function
override fun inOnCreateView(mRootView: ViewGroup, savedInstanceState: Bundle?) {
val homeActivity = activity as HomeNavHostActivity
homeActivity.toolbar_id?.visibility = View.VISIBLE
homeActivity.toolbar_search_icon_id.visibility = View.VISIBLE
homeActivity.toolbar_add_icon_id.visibility = View.GONE
homeActivity.home_view_layout?.visibility = View.VISIBLE
homeActivity.bottom_layout?.visibility = View.VISIBLE
homeActivity.toolbar_title_tv.text = "Home"
homeActivity.toolbar_search_icon_id.setOnClickListener() {
showSearchDialog(mRootView)
}
homeActivity.cancel_text.setOnClickListener() {
homeActivity.search_layout.visibility = View.GONE
homeActivity.toolbar_title_tv.visibility = View.VISIBLE
homeActivity.search_view?.setQuery("", false)
homeActivity.search_view?.clearFocus()
}
val dialogHelper by inject<MaterialDialogHelper>()
setupProgressDialog(viewModel.showHideProgressDialog, dialogHelper)
if (isNetworkAvailable(requireContext())) {
viewModel.getSkipFilterList(zipcode, area)
// viewModel.getSkipHomeData()
} else {
showAlertDialog(getString(R.string.no_internet))
}
attachViewModel()
}
Related
How to scan barcode lines with VARCHAR Chars For example OfficeEqp35023U11 In android Kotlin
Struggling to scan this asset image
Struggling to scan this asset image
class BarcodeScannerActivity : AppCompatActivity(), ZXingScannerView.ResultHandler {
private var mScannerView: ZXingScannerView? = null
lateinit var apiInterface: APIInterface
public override fun onCreate(state: Bundle?) {
super.onCreate(state)
setContentView(R.layout.activity_barcode_scanner)
ssoId = intent.getStringExtra("initiator")
val contentFrame = findViewById<View>(R.id.content_frame) as ViewGroup
mScannerView = ZXingScannerView(this)
contentFrame.addView(mScannerView)
}
public override fun onResume() {
super.onResume()
mScannerView!!.setResultHandler(this)
mScannerView!!.startCamera()
}
public override fun onPause() {
super.onPause()
mScannerView!!.stopCamera()
}
override fun handleResult(rawResult: Result) {
Toast.makeText(
this, "Contents = " + rawResult.text +
", Format = " + rawResult.barcodeFormat.toString(), Toast.LENGTH_SHORT
).show()
var result = rawResult.text
if (result.isDigitsOnly()) {
assetTag = result.filter { it.isLetterOrDigit() }
mScannerView!!.stopCamera()
apiInterface = APIClient.client!!.create(APIInterface::class.java)
val call: Call<Verifiedd> =
apiInterface.saveVerification(assetTag, ssoId, ssoId, "Verified", "Verified")
call.enqueue(object : Callback<Verifiedd> {
override fun onResponse(call: Call<Verifiedd>, response: Response<Verifiedd>) {
if (response.body() != null) {
lovelyProgressDialog?.dismiss()
Log.d("TAG", response.code().toString() + "")
var displayResponse = ""
val resource: Verifiedd = response.body()!!
responseCode = resource.responseCode
responseMessage = resource.responseMessage
if (responseMessage == "Data persisted successfully " || responseMessage.equals(
"Data persisted successfully "
)
) {
Toasty.normal(
this#BarcodeScannerActivity,
"",
Toasty.LENGTH_LONG
).show()
} else if (responseMessage == "" || responseMessage.equals(
""
)
) {
Toasty.normal(
this#BarcodeScannerActivity,
"Invalid Asset Verification status values",
Toasty.LENGTH_LONG
).show()
val intent =
Intent(this#BarcodeScannerActivity, BranchItemsActivity::class.java)
intent.flags =
Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
intent.putExtra(
"initiator", ssoId
)
startActivity(intent)
}
}
}
override fun onFailure(call: Call<Verifiedd>, t: Throwable) {
Toasty.normal(
this#BarcodeScannerActivity,
"Server Error",
Toasty.LENGTH_LONG
).show()
}
})
I have a recyclerview where view type is edittext and on value entered of the edittext, other edittext values should be added with current value.
value entered in edittext item 1 of recyclerview and value entered in edittext item 2 should be the sum in the edittext item 3 which is not editable.
So in below code, the type 'Edittext' is used to identify that these edittext have text watchers and on change of these editttext values, the values of calculations be set in else part.
How to update the data in else code when i am updating the text in editable edittext. this is my code below.
Anyone having solution,
// enter code here
class ProfileDataSubAdapter(
val context: Context,
var repeatedDataList: RealmList<EntityDetails>
) : RecyclerView.Adapter<ProfileDataSubAdapter.DataAdapterViewHolder>() {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): DataAdapterViewHolder {
val layout = when (viewType) {
TYPE_EDITTEXT -> R.layout.item_edittext
TYPE_SPINNER -> R.layout.item_spinner
TYPE_CALCULATE -> R.layout.item_edittext
else -> throw IllegalArgumentException("Invalid view type")
}
val view = LayoutInflater
.from(context)
.inflate(layout, parent, false)
return DataAdapterViewHolder(view)
}
override fun onBindViewHolder(holder: DataAdapterViewHolder, position: Int) {
holder.bind(repeatedDataList[position], context, position)
}
fun getRepeatedList(): RealmList<EntityDetails>? {
repeatedDataList.forEach {
if (it.ValueType.equals("EditText") && it.UserEnterValue?.isNullOrEmpty()!!) {
Toast.makeText(context, "Field ${it.EntityName} is empty", Toast.LENGTH_LONG).show()
return null;
}
}
return repeatedDataList
}
override fun getItemCount(): Int = repeatedDataList.size
override fun getItemViewType(position: Int): Int {
if (repeatedDataList[position]?.ValueType == "EditText") {
return TYPE_EDITTEXT
} else if (repeatedDataList[position]?.ValueType == "RadioButton") {
return TYPE_SPINNER
} else
return TYPE_CALCULATE
}
companion object {
private const val TYPE_EDITTEXT = 0
private const val TYPE_SPINNER = 1
private const val TYPE_CALCULATE = 3
}
inner class DataAdapterViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bindEdittextData(item: EntityDetails, position: Int) {
//Do your view assignment here from the data model
itemView.findViewById<TextView>(R.id.tv_edit_text_label)?.text = item.EntityName
val content = itemView.findViewById<EditText>(R.id.et_content)
if (item.UserEnterValue?.isNotEmpty()!!) {
content.setText(item.UserEnterValue)
}
//if type is edittext then set text watchers here
if (item.ValueType == "EditText") {
content.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
repeatedDataList[position]?.UserEnterValue = p0.toString()
}
override fun afterTextChanged(p0: Editable?) {
}
})
}
// else if type is calculation set the total here
else {
content.setInputType(InputType.TYPE_NULL)
}
}
fun bindSpinnerData(item: EntityDetails, context: Context) {
//Do your view assignment here from the data model
itemView.findViewById<TextView>(R.id.tv_spinner_label)?.text = item.EntityName
val spinner = itemView.findViewById<Spinner>(R.id.spinner_content)
spinner.adapter = ArrayAdapter<String>(
context,
R.layout.row_spinner,
R.id.txt_content,
item.Values?.map { it.Value } as MutableList<String>
)
// spnr_house.setSelection(getIndexSpinner(spnr_house, noOfYearsInCurrentHouse?.trim()))
spinner.setSelection(item.Values!!.indexOfFirst {
it.IsSelected == true
}, false)
// spinner.setSelection()
spinner.onItemSelectedListener =
object : AdapterView.OnItemSelectedListener {
override fun onNothingSelected(view: AdapterView<*>?) {
}
override fun onItemSelected(
parentView: AdapterView<*>?,
selectedView: View?,
pos: Int,
id: Long
) {
val selectedItem =
spinner.getItemAtPosition(pos)
.toString()
if (selectedItem != "Select") {
item.Values?.find { it.Value == selectedItem }?.IsSelected =
true
val list = item.Values?.filter { it.Value != selectedItem }
list?.forEach { it.IsSelected = false }
}
}
}
}
fun bind(
dataModel: EntityDetails?,
context: Context,
position: Int
) {
if (dataModel?.ValueType == "EditText" || dataModel?.ValueType == "Calculation")
bindEdittextData(dataModel, position)
else if (dataModel?.ValueType == "RadioButton")
bindSpinnerData(dataModel, context)
}
}
}
//end code
In the Adapter method. i am able to print list elements in updateUsers(newUsers: List)
that means I am getting dataset in the Adapter, but none of the Adapter methods are getting called.
I have set the layout manager too.
I have breakpoints for All adapter methods onCreateViewHolder, onBindViewHolder. but control is not entering code block.
class MainActivity : AppCompatActivity() {
lateinit var viewModel: ListViewModel
private val usersAdapter = UserListAdapter(arrayListOf(),this)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProviders.of(this).get(ListViewModel::class.java)
viewModel.refresh()
usersList.apply {
layoutManager = LinearLayoutManager(this.context)
adapter = usersAdapter
}
usersList.adapter = usersAdapter
observeViewModel()
}
fun observeViewModel() {
viewModel.users.observe(this, Observer {
it?.let {
it.forEach {
Log.d("Each Item", it.toString());
}
loading_view.visibility = View.VISIBLE
usersAdapter.updateUsers(it)
}
})
viewModel.userLoadError.observe(this, Observer {
it?.let {
list_error.visibility = if (it) View.VISIBLE else View.GONE
}
})
viewModel.loading.observe(this, Observer {
it?.let {
loading_view.visibility = if (it) View.VISIBLE else View.GONE
if (it) {
list_error.visibility = View.GONE
usersList.visibility = View.GONE
}
}
})
}
}
class UserListAdapter(private var users: ArrayList<User>, private val context : Context) : RecyclerView.Adapter<UserListAdapter.UserViewHolder>() {
fun updateUsers(newUsers: List<User>) {
newUsers.forEach() {
Log.d("updateUsers", it.firstName)
}
users.clear()
users.addAll(newUsers)
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) : UserViewHolder{
val layoutInflator = LayoutInflater.from(parent.context)
val view = layoutInflator.inflate(R.layout.item_layout,parent,false)
return UserViewHolder(view)
}
override fun getItemCount():Int {
return users.size
}
override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
holder.bind(users[position])
}
class UserViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private val imageView = view.imageView
private val userName = view.name
private val userEmail = view.email
fun bind(country: User) {
userName.text = country.firstName + " " + country.lastName
userEmail.text = country.email
imageView.loadImage(country.avatar)
}
}
}
I am not exactly sure why your code is not working, here I have implemented using your code and it's working.
MainActivity
class MainActivity : AppCompatActivity() {
private lateinit var viewModel: ListViewModel
private val usersAdapter = UserListAdapter(arrayListOf(), this)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProviders.of(this).get(ListViewModel::class.java)
viewModel.refresh()
usersList.apply {
layoutManager = LinearLayoutManager(this.context,
RecyclerView.VERTICAL, false)
adapter = usersAdapter
}
// usersList.adapter = usersAdapter // Don't need, you already set the
// adapter above.
observeViewModel()
}
private fun observeViewModel() {
viewModel.users.observe(this, Observer {
it?.let {
it.forEach {
Log.d("Each Item", it.toString());
}
//loading_view.visibility = View.VISIBLE
usersAdapter.updateUsers(it)
}
})
// commented for simplicity
//viewModel.userLoadError.observe(this, Observer {
// it?.let {
//list_error.visibility = if (it) View.VISIBLE else View.GONE
// }
//})
// viewModel.loading.observe(this, Observer {
// it?.let {
// loading_view.visibility = if (it) View.VISIBLE else View.GONE
// if (it) {
// list_error.visibility = View.GONE
// usersList.visibility = View.GONE
// }
//
// }
// })
}
}
UserListAdapter
class UserListAdapter(private var users: ArrayList<User>, private val context : Context) : RecyclerView.Adapter<UserListAdapter.UserViewHolder>() {
fun updateUsers(newUsers: List<User>) {
newUsers.forEach() {
Log.d("updateUsers", it.firstName)
}
users.clear()
users.addAll(newUsers)
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) : UserViewHolder {
val inflater = LayoutInflater.from(parent.context)
val view = inflater.inflate(R.layout.item_layout,parent,false)
return UserViewHolder(view)
}
override fun getItemCount():Int {
return users.size
}
override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
holder.bind(users[position])
}
class UserViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private val imageView = view.imageView
private val userName = view.name
private val userEmail = view.email
fun bind(country: User) {
userName.text = country.firstName + " " + country.lastName
userEmail.text = country.email
//imageView.loadImage(country.avatar)
}
}
}
ListViewModel
class ListViewModel: ViewModel() {
val users : MutableLiveData<List<User>> = MutableLiveData()
fun refresh() {
val userList = mutableListOf<User>()
userList.add(User(
"User1 First Name",
"User1 last Name",
"example#gmail.com"
))
userList.add(User(
"User2 First Name",
"User2 First Name",
"example#gmail.com"
))
userList.add(User(
"User3 First Name",
"User3 First Name",
"example#gmail.com"
))
userList.add(User(
"User4 First Name",
"User4 First Name",
"example#gmail.com"
))
userList.add(User(
"User5 First Name",
"User5 First Name",
"example#gmail.com"
))
userList.add(User(
"User6 First Name",
"User6 First Name",
"example#gmail.com"
))
users.value = userList
}
}
Hope this helps.
Hello I am New to Programming i just created an application that get the data from server every second i just wants to changethe background of my RecyclerViews holder's bid and ask position if the data if grater or lower then previous.
for example my init data at bid price is 4000 after one second if my bid price of the item is increase and then the position at recyclerview's change the background color of it.
i just implement this code but its randomly changing the background also when the price are not changed.
class Adapter(private val product: ArrayList<Products>) :
RecyclerView.Adapter<McxAdapter.CustomViewHolder>() {
var olddatabid: ArrayList<String> = ArrayList()
var newdatabid: ArrayList<String> = ArrayList()
var olddataask: ArrayList<String> = ArrayList()
var newdataask: ArrayList<String> = ArrayList()
fun addNewStatutes(items: ArrayList<Products>) {
product.clear()
this.product.addAll(items)
if (product.isNotEmpty()) {
notifyDataSetChanged()
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomViewHolder {
val itemView = LayoutInflater.from(parent.context)
.inflate(R.layout.item_mcx, parent, false)
return CustomViewHolder(itemView)
}
override fun onBindViewHolder(holder: CustomViewHolder, position: Int) {
try {
val datum = product[position]
holder.txtSymbol.text = datum.symbol
holder.txtdate.text = datum.serExp
holder.txtBuy.text = datum.buyPrice
holder.txtSell.text = datum.sellPrice
holder.txtLtp.text = datum.lastTradedPrice
holder.txtHigh.text = datum.high
holder.txtLow.text = datum.low
holder.txtOpen.text = datum.open
holder.txtClose.text = datum.close
holder.txtChange.text = datum.netChangeInRs
if (newdatabid.size < product.size) {
newdatabid.add(datum.buyPrice.toString())
}
if (olddatabid.size < product.size) {
olddatabid.add(datum.buyPrice.toString())
}
if (newdataask.size < product.size) {
newdataask.add(datum.sellPrice.toString())
}
if (olddataask.size < product.size) {
olddataask.add(datum.sellPrice.toString())
}
newdatabid[position] = datum.buyPrice.toString()
newdataask[position] = datum.sellPrice.toString()
if (newdatabid[position].toFloat() > olddatabid[position].toFloat()) {
holder.txtBuy.setBackgroundColor(Color.BLUE)
}
if (newdatabid[position].toFloat() < olddatabid[position].toFloat()) {
holder.txtBuy.setBackgroundColor(Color.RED)
}
if (newdataask[position].toFloat() > olddataask[position].toFloat()) {
holder.txtSell.setBackgroundColor(Color.BLUE)
}
if (newdataask[position].toFloat() < olddataask[position].toFloat()) {
holder.txtSell.setBackgroundColor(Color.RED)
}
olddatabid[position] = newdatabid[position]
olddataask[position] = newdataask[position]
} catch (e: Exception) {
}
}
override fun getItemCount(): Int {
return if (product.size > 0 && product.isNotEmpty()) {
product.size
} else {
0
}
}
inner class CustomViewHolder(view: View) : RecyclerView.ViewHolder(view) {
internal var txtSymbol: TextView = itemView.findViewById(R.id.scriptname)
internal var txtdate: TextView = itemView.findViewById(R.id.date)
internal var txtBuy: TextView = itemView.findViewById(R.id.buy)
internal var txtSell: TextView = itemView.findViewById(R.id.sell)
internal var txtLtp: TextView = itemView.findViewById(R.id.currentvalue)
internal var txtHigh: TextView = itemView.findViewById(R.id.high)
internal var txtLow: TextView = itemView.findViewById(R.id.low)
internal var txtOpen: TextView = itemView.findViewById(R.id.open)
internal var txtClose: TextView = itemView.findViewById(R.id.close)
internal var txtChange: TextView = itemView.findViewById(R.id.change)
internal var txtRupp: TextView = itemView.findViewById(R.id.rupp)
}
}
Try to remove if statements in if else or when statement, then check the results
if (newdatabid.size < product.size) {
newdatabid.add(datum.buyPrice.toString())
}
if (olddatabid.size < product.size) {
olddatabid.add(datum.buyPrice.toString())
}
if (newdataask.size < product.size) {
newdataask.add(datum.sellPrice.toString())
}
if (olddataask.size < product.size) {
olddataask.add(datum.sellPrice.toString())
}
Make your class a data class and use AsyncListDiffer.submitList to update adapter
Here is a good article about implementing diffutil https://medium.com/#iammert/using-diffutil-in-android-recyclerview-bdca8e4fbb00
I am trying to run an application that I rewrote in Kotlin from the following link:
https://www.androidhive.info/RxJava/android-rxjava-networking-with-retrofit-gson-notes-app/
The example was originally code base was coded in Java. I am getting the following error upon running the application.
2018-11-16 12:12:38.173 11843-11843/com.touchsides.rxjavanetworking E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.touchsides.rxjavanetworking, PID: 11843
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.touchsides.rxjavanetworking/com.touchsides.rxjavanetworking.view.MainActivity}: java.lang.InstantiationException: java.lang.Class<com.touchsides.rxjavanetworking.view.MainActivity> cannot be instantiated
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2843)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.InstantiationException: java.lang.Class<com.touchsides.rxjavanetworking.view.MainActivity> cannot be instantiated
at java.lang.Class.newInstance(Native Method)
at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:69)
at android.support.v4.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:43)
at android.app.Instrumentation.newActivity(Instrumentation.java:1215)
The MainActivity code is as follows:
abstract class MainActivity : AppCompatActivity()
{
lateinit var apiService: ApiService
var disposable = CompositeDisposable()
lateinit var mAdapter: NotesAdapter
var noteList = ArrayList<Note>()
companion object
{
val TAG = MainActivity::class.java.simpleName;
}
#BindView(R.id.coordinator_layout) var coordinatorLayout: CoordinatorLayout? = null
#BindView(R.id.recycler_view) var recyclerView: RecyclerView? = null
#BindView(R.id.txt_empty_notes_view) var noNotesView: TextView? = null
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
val toolbar = findViewById<Toolbar>(R.id.toolbar)
toolbar.setTitle(getString(R.string.activity_title_home))
setSupportActionBar(toolbar)
fab.setOnClickListener { view ->
showNoteDialog(false, null, -1);
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean
{
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.menu_main, menu)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean
{
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
return when (item.itemId)
{
R.id.action_settings -> true
else -> super.onOptionsItemSelected(item)
}
}
/**
* Registering new user
* sending unique id as device identification
* https://developer.android.com/training/articles/user-data-ids.html
*/
private fun registerUser()
{
// unique id to identify the device
val uniqueId = UUID.randomUUID().toString()
disposable.add(apiService.register(uniqueId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribeWith(
object : DisposableSingleObserver<User>()
{
override fun onSuccess(user: User)
{
// Storing user API Key in preferences
user.apiKey?.let { PrefUtils.storeApiKey(applicationContext, it) }
Toast.makeText(applicationContext,
"Device is registered successfully! ApiKey: " + PrefUtils.getApiKey(applicationContext),
Toast.LENGTH_LONG).show()
}
override fun onError(e: Throwable)
{
Log.e(TAG, "onError: " + e.message)
showError(e)
}
}))
}
/**
* Creating new note
*/
private fun createNote(note: String)
{
disposable.add(apiService.createNote(note).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribeWith(
object : DisposableSingleObserver<Note>()
{
override fun onSuccess(note: Note)
{
if (!TextUtils.isEmpty(note.error))
{
Toast.makeText(applicationContext, note.error, Toast.LENGTH_LONG).show()
return
}
Log.d(TAG, "new note created: " + note.id + ", " + note.note + ", " + note.timestamp)
// Add new item and notify adapter
noteList.add(0, note)
mAdapter.notifyItemInserted(0)
toggleEmptyNotes()
}
override fun onError(e: Throwable)
{
Log.e(TAG, "onError: " + e.message)
showError(e)
}
}))
}
/**
* Updating a note
*/
private fun updateNote(noteId: Int, note: String, position: Int)
{
disposable.add(apiService.updateNote(noteId,
note).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribeWith(object :
DisposableCompletableObserver()
{
override fun onComplete()
{
Log.d(TAG, "Note updated!")
val n = noteList.get(position)
n.note = (note)
// Update item and notify adapter
noteList.set(position, n)
mAdapter.notifyItemChanged(position)
}
override fun onError(e: Throwable)
{
Log.e(TAG, "onError: " + e.message)
showError(e)
}
}))
}
/**
* Deleting a note
*/
private fun deleteNote(noteId: Int, position: Int)
{
Log.e(TAG, "deleteNote: $noteId, $position")
disposable.add(apiService.deleteNote(noteId).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribeWith(
object : DisposableCompletableObserver()
{
override fun onComplete()
{
Log.d(TAG, "Note deleted! $noteId")
// Remove and notify adapter about item deletion
noteList.removeAt(position)
mAdapter.notifyItemRemoved(position)
Toast.makeText(this#MainActivity, "Note deleted!", Toast.LENGTH_SHORT).show()
toggleEmptyNotes()
}
override fun onError(e: Throwable)
{
Log.e(TAG, "onError: " + e.message)
showError(e)
}
}))
}
/**
* Shows alert dialog with EditText options to enter / edit
* a note.
* when shouldUpdate=true, it automatically displays old note and changes the
* button text to UPDATE
*/
private fun showNoteDialog(shouldUpdate: Boolean, note: Note?, position: Int)
{
val layoutInflaterAndroid = LayoutInflater.from(applicationContext)
val view = layoutInflaterAndroid.inflate(R.layout.note_dialog, null)
val alertDialogBuilderUserInput = AlertDialog.Builder(this#MainActivity)
alertDialogBuilderUserInput.setView(view)
val inputNote = view.findViewById<EditText>(R.id.note)
val dialogTitle = view.findViewById<TextView>(R.id.dialog_title)
dialogTitle.setText(if (!shouldUpdate) getString(R.string.lbl_new_note_title) else getString(R.string.lbl_edit_note_title))
if (shouldUpdate && note != null)
{
inputNote.setText(note.note)
}
alertDialogBuilderUserInput.setCancelable(false).setPositiveButton(if (shouldUpdate) "update" else "save",
DialogInterface.OnClickListener { dialogBox, id -> })
.setNegativeButton("cancel", DialogInterface.OnClickListener { dialogBox, id -> dialogBox.cancel() })
val alertDialog = alertDialogBuilderUserInput.create()
alertDialog.show()
alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(View.OnClickListener {
// Show toast message when no text is entered
if (TextUtils.isEmpty(inputNote.text.toString()))
{
Toast.makeText(this#MainActivity, "Enter note!", Toast.LENGTH_SHORT).show()
return#OnClickListener
} else
{
alertDialog.dismiss()
}
// check if user updating note
if (shouldUpdate && note != null)
{
// update note by it's id
updateNote(note.id, inputNote.text.toString(), position)
} else
{
// create new note
createNote(inputNote.text.toString())
}
})
}
/**
* Opens dialog with Edit - Delete options
* Edit - 0
* Delete - 0
*/
private fun showActionsDialog(position: Int)
{
val colors = arrayOf<CharSequence>("Edit", "Delete")
val builder = AlertDialog.Builder(this)
builder.setTitle("Choose option")
builder.setItems(colors) { dialog, which ->
if (which == 0)
{
showNoteDialog(true, noteList.get(position), position)
} else
{
deleteNote(noteList.get(position).id, position)
}
}
builder.show()
}
private fun toggleEmptyNotes()
{
if (noteList.size > 0)
{
noNotesView?.setVisibility(View.GONE)
} else
{
noNotesView?.setVisibility(View.VISIBLE)
}
}
/**
* Showing a Snackbar with error message
* The error body will be in json format
* {"error": "Error message!"}
*/
fun showError(e: Throwable)
{
var message = ""
try
{
if (e is IOException)
{
message = "No internet connection!"
}
else (e is HttpException)
{
var error = e as HttpException
var errorBody = error.response().errorBody().toString()
val jObj = JSONObject(errorBody)
message = jObj.getString("error")
}
}
catch (e1: IOException)
{
e1.printStackTrace()
}
catch (e1: JSONException)
{
e1.printStackTrace()
}
catch (e1: Exception)
{
e1.printStackTrace()
}
if (TextUtils.isEmpty(message))
{
message = "Unknown error occurred! Check LogCat.";
}
val snackbar = coordinatorLayout?.let { Snackbar.make(it, message, Snackbar.LENGTH_LONG) }
val sbView = snackbar?.getView()
val textView = sbView?.findViewById<TextView>(android.support.design.R.id.snackbar_text)
textView?.setTextColor(Color.YELLOW)
snackbar?.show()
}
fun whiteNotificationBar(view: View)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
{
var flags = view.getSystemUiVisibility();
flags = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
view.setSystemUiVisibility(flags);
getWindow().setStatusBarColor(Color.WHITE);
}
}
override fun onDestroy()
{
super.onDestroy()
disposable.dispose()
}
}
I found out what the issue was. It seems by using the code complete option it ended up making the MainActivity class abstract
abstract class MainActivity : AppCompatActivity()
{
/// code base
}
instead of
class MainActivity : AppCompatActivity()
{
// code base
}