mirror of
https://github.com/hmalik144/EasyCC_Master.git
synced 2026-01-31 02:41:47 +00:00
Viewmodel updated to use live data
Main activity dialogs changed code clean up
This commit is contained in:
BIN
.idea/caches/build_file_checksums.ser
generated
BIN
.idea/caches/build_file_checksums.ser
generated
Binary file not shown.
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -39,7 +39,7 @@
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
||||
@@ -34,9 +34,7 @@ android {
|
||||
def ccApiKey = properties.getProperty("cc_api_key", "")
|
||||
|
||||
it.buildConfigField 'String', "CC_API_KEY", ccApiKey
|
||||
|
||||
it.resValue 'string', "api_key", ccApiKey
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import com.appttude.h_mal.easycc.mvvm.data.network.response.ResponseObject
|
||||
/**
|
||||
* Main entry point for accessing currency data.
|
||||
*/
|
||||
|
||||
interface Repository {
|
||||
|
||||
suspend fun getData(fromCurrency: String, toCurrency: String): ResponseObject
|
||||
|
||||
@@ -7,14 +7,12 @@ import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.WindowManager
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.TextView
|
||||
import com.appttude.h_mal.easycc.R
|
||||
import kotlinx.android.synthetic.main.custom_dialog.*
|
||||
|
||||
class CustomDialogClass(
|
||||
context: Context,
|
||||
val textView: TextView,
|
||||
val viewModel: MainViewModel
|
||||
private val clickListener: ClickListener
|
||||
) : Dialog(context) {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -24,7 +22,11 @@ class CustomDialogClass(
|
||||
window!!.setBackgroundDrawableResource(android.R.color.transparent)
|
||||
window!!.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
|
||||
|
||||
val arrayAdapter = ArrayAdapter.createFromResource(context, R.array.currency_arrays, android.R.layout.simple_list_item_1)
|
||||
val arrayAdapter =
|
||||
ArrayAdapter.createFromResource(
|
||||
context, R.array.currency_arrays,
|
||||
android.R.layout.simple_list_item_1)
|
||||
|
||||
list_view.adapter = arrayAdapter
|
||||
|
||||
search_text.addTextChangedListener(object : TextWatcher {
|
||||
@@ -36,15 +38,12 @@ class CustomDialogClass(
|
||||
})
|
||||
|
||||
list_view.setOnItemClickListener{ adapterView, _, i, _ ->
|
||||
if (textView.tag == "top"){
|
||||
viewModel.rateIdFrom = adapterView.getItemAtPosition(i).toString()
|
||||
}else{
|
||||
viewModel.rateIdTo = adapterView.getItemAtPosition(i).toString()
|
||||
}
|
||||
textView.text = adapterView.getItemAtPosition(i).toString()
|
||||
viewModel.getExchangeRate()
|
||||
|
||||
clickListener.onText(adapterView.getItemAtPosition(i).toString())
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface ClickListener{
|
||||
fun onText(currencyName: String)
|
||||
}
|
||||
@@ -3,12 +3,12 @@ package com.appttude.h_mal.easycc.mvvm.ui.app
|
||||
import android.os.Bundle
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProviders
|
||||
import com.appttude.h_mal.easycc.R
|
||||
import com.appttude.h_mal.easycc.databinding.ActivityMainBinding
|
||||
@@ -23,6 +23,7 @@ import org.kodein.di.generic.instance
|
||||
class MainActivity : AppCompatActivity(), RateListener, KodeinAware, View.OnClickListener {
|
||||
|
||||
override val kodein by kodein()
|
||||
// Retrieve MainViewModelFactory via dependency injection
|
||||
private val factory: MainViewModelFactory by instance()
|
||||
|
||||
companion object {
|
||||
@@ -31,31 +32,44 @@ class MainActivity : AppCompatActivity(), RateListener, KodeinAware, View.OnClic
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
// Keyboard is not overlapping views
|
||||
this.window.setSoftInputMode(
|
||||
WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN or
|
||||
WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
|
||||
|
||||
this.window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN or WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
|
||||
viewModel = ViewModelProviders.of(this, factory)
|
||||
.get(MainViewModel::class.java)
|
||||
|
||||
val binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
|
||||
viewModel = ViewModelProviders.of(this, factory).get(MainViewModel::class.java)
|
||||
|
||||
binding.viewmodel = viewModel
|
||||
binding.lifecycleOwner = this
|
||||
|
||||
viewModel.rateListener = this
|
||||
|
||||
intent.extras?.apply {
|
||||
val itemOne = getString("parse_1")
|
||||
val itemTwo = getString("parse_2")
|
||||
|
||||
if (!itemOne.isNullOrEmpty() && !itemTwo.isNullOrEmpty()){
|
||||
viewModel.rateIdTo = itemOne
|
||||
viewModel.rateIdFrom = itemTwo
|
||||
|
||||
viewModel.getExchangeRate()
|
||||
}
|
||||
// Bind viewmodel to layout with view binding
|
||||
DataBindingUtil
|
||||
.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
|
||||
.apply {
|
||||
viewmodel = viewModel
|
||||
lifecycleOwner = this@MainActivity
|
||||
}
|
||||
|
||||
viewModel.start()
|
||||
viewModel.initiate(intent.extras)
|
||||
|
||||
setUpListeners()
|
||||
setUpObservers()
|
||||
}
|
||||
|
||||
private fun setUpObservers() {
|
||||
viewModel.operationStartedListener.observe(this, Observer {
|
||||
progressBar.hideView(false)
|
||||
})
|
||||
viewModel.operationFinishedListener.observe(this, Observer { pair ->
|
||||
progressBar.hideView(true)
|
||||
if (pair.first){
|
||||
bottomInsertValues.clearEditText()
|
||||
topInsertValue.clearEditText()
|
||||
}else{
|
||||
pair.second?.let { DisplayToast(it) }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun setUpListeners(){
|
||||
topInsertValue.addTextChangedListener(textWatcherClass)
|
||||
bottomInsertValues.addTextChangedListener(textWatcherClass2)
|
||||
|
||||
@@ -64,7 +78,13 @@ class MainActivity : AppCompatActivity(), RateListener, KodeinAware, View.OnClic
|
||||
}
|
||||
|
||||
private fun showCustomDialog(view: View?) {
|
||||
val dialogClass = CustomDialogClass(this, view as TextView, viewModel)
|
||||
|
||||
val dialogClass = CustomDialogClass(this, object : ClickListener {
|
||||
override fun onText(currencyName: String) {
|
||||
(view as TextView).text = currencyName
|
||||
viewModel.setCurrencyName(view.tag, currencyName)
|
||||
}
|
||||
})
|
||||
dialogClass.show()
|
||||
}
|
||||
|
||||
@@ -90,17 +110,13 @@ class MainActivity : AppCompatActivity(), RateListener, KodeinAware, View.OnClic
|
||||
private val textWatcherClass: TextWatcher = object : TextWatcher {
|
||||
override fun onTextChanged(s: CharSequence, st: Int, b: Int, c: Int) {
|
||||
bottomInsertValues.removeTextChangedListener(textWatcherClass2)
|
||||
if (topInsertValue.text.isNullOrEmpty()) {
|
||||
if (topInsertValue.text.isNullOrEmpty())
|
||||
bottomInsertValues.setText("")
|
||||
}
|
||||
}
|
||||
|
||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
try {
|
||||
viewModel.setBottomValue(s.toString(), bottomInsertValues)
|
||||
} catch (e: NumberFormatException) {
|
||||
Log.e(this.javaClass.simpleName, "no numbers inserted")
|
||||
}
|
||||
bottomInsertValues.setText(viewModel.getConversion(s.toString()))
|
||||
bottomInsertValues.addTextChangedListener(textWatcherClass2)
|
||||
}
|
||||
}
|
||||
@@ -108,17 +124,13 @@ class MainActivity : AppCompatActivity(), RateListener, KodeinAware, View.OnClic
|
||||
private val textWatcherClass2: TextWatcher = object : TextWatcher {
|
||||
override fun onTextChanged(s: CharSequence, st: Int, b: Int, c: Int) {
|
||||
topInsertValue.removeTextChangedListener(textWatcherClass)
|
||||
if (bottomInsertValues.text.isNullOrEmpty()) {
|
||||
if (bottomInsertValues.text.isNullOrEmpty())
|
||||
topInsertValue.clearEditText()
|
||||
}
|
||||
}
|
||||
|
||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
try {
|
||||
viewModel.setTopValue(s.toString(), topInsertValue)
|
||||
} catch (e: NumberFormatException) {
|
||||
Log.e(this.javaClass.simpleName, "no numbers inserted")
|
||||
}
|
||||
topInsertValue.setText(viewModel.getReciprocalConversion(s.toString()))
|
||||
topInsertValue.addTextChangedListener(textWatcherClass)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,79 +1,105 @@
|
||||
package com.appttude.h_mal.easycc.mvvm.ui.app
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.widget.EditText
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.appttude.h_mal.easycc.mvvm.data.repository.Repository
|
||||
import com.appttude.h_mal.easycc.mvvm.utils.toTwoDp
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.IOException
|
||||
import java.text.DecimalFormat
|
||||
|
||||
private const val TAG = "MainViewModel"
|
||||
class MainViewModel(
|
||||
private val repository: Repository
|
||||
) : ViewModel(){
|
||||
|
||||
private val defaultValue by lazy { repository.getArrayList()[0] }
|
||||
private val conversionPairs by lazy { repository.getConversionPair() }
|
||||
|
||||
var rateIdFrom: String? = conversionPairs.first ?: defaultValue
|
||||
var rateIdTo: String? = conversionPairs.second ?: defaultValue
|
||||
|
||||
var topVal: String? = null
|
||||
var bottomVal: String? = null
|
||||
|
||||
var rateListener: RateListener? = null
|
||||
var rateIdFrom: String? = null
|
||||
var rateIdTo: String? = null
|
||||
|
||||
//operation results livedata based on outcome of operation
|
||||
val operationSuccess = MutableLiveData<Pair<Boolean, String>>()
|
||||
val currencyRate = MutableLiveData<Double>()
|
||||
val operationStartedListener = MutableLiveData<Boolean>()
|
||||
val operationFinishedListener = MutableLiveData<Pair<Boolean, String?>>()
|
||||
|
||||
private var conversionRate: Double = 0.00
|
||||
|
||||
fun getExchangeRate(){
|
||||
rateListener?.onStarted()
|
||||
|
||||
operationStartedListener.postValue(false)
|
||||
|
||||
if (rateIdFrom.isNullOrEmpty() || rateIdTo.isNullOrEmpty()){
|
||||
rateListener?.onFailure("Select currencies")
|
||||
operationFinishedListener.postValue(Pair(false, "Select currencies"))
|
||||
return
|
||||
}
|
||||
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
if (rateIdFrom == rateIdTo){
|
||||
conversionRate = 1.00
|
||||
operationFinishedListener.postValue(Pair(true, null))
|
||||
return
|
||||
}
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val exchangeResponse = repository.getData(rateIdFrom!!, rateIdTo!!)
|
||||
repository.setConversionPair(rateIdFrom!!, rateIdTo!!)
|
||||
|
||||
exchangeResponse.results?.iterator()?.next()?.value?.let {
|
||||
rateListener?.onSuccess()
|
||||
operationFinishedListener.postValue(Pair(true, null))
|
||||
conversionRate = it.value
|
||||
return@launch
|
||||
}
|
||||
|
||||
}catch(e: IOException){
|
||||
rateListener?.onFailure(e.message ?: "Currency Retrieval failed")
|
||||
operationFinishedListener.postValue(Pair(false, e.message ?: "Currency Retrieval failed"))
|
||||
return@launch
|
||||
}
|
||||
rateListener?.onFailure("Failed to retrieve rate")
|
||||
|
||||
operationFinishedListener.postValue(Pair(false, "Failed to retrieve rate"))
|
||||
}
|
||||
}
|
||||
|
||||
fun setBottomValue(fromValue : String, editText: EditText) {
|
||||
fun getConversion(fromValue: String): String? {
|
||||
return try {
|
||||
val fromValDouble = fromValue.toDouble()
|
||||
val bottomVal1 = (fromValDouble * conversionRate).toTwoDp()
|
||||
editText.setText(bottomVal1.toBigDecimal().toPlainString())
|
||||
bottomVal1.toBigDecimal().toPlainString()
|
||||
}catch (e: NumberFormatException) {
|
||||
Log.e(TAG, "no numbers inserted")
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun setTopValue(toValue : String, editText: EditText) {
|
||||
fun getReciprocalConversion(toValue: String): String? {
|
||||
return try {
|
||||
val toDoubleVal = toValue.toDouble()
|
||||
val newTopVal = toDoubleVal.times((1/conversionRate)).toTwoDp()
|
||||
editText.setText(newTopVal.toBigDecimal().toPlainString())
|
||||
newTopVal.toBigDecimal().toPlainString()
|
||||
} catch (e: NumberFormatException) {
|
||||
Log.e(TAG, "no numbers inserted")
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun start(){
|
||||
if (rateIdFrom != rateIdTo){
|
||||
fun setCurrencyName(tag: Any?, currencyName: String){
|
||||
if (tag.toString() == "top"){
|
||||
rateIdFrom = currencyName
|
||||
}else{
|
||||
rateIdTo = currencyName
|
||||
}
|
||||
getExchangeRate()
|
||||
}
|
||||
|
||||
fun initiate(extras: Bundle?) {
|
||||
rateIdFrom = extras?.getString("parse_1") ?: conversionPairs.first
|
||||
rateIdTo = extras?.getString("parse_2") ?: conversionPairs.second
|
||||
|
||||
getExchangeRate()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -58,7 +58,6 @@
|
||||
android:layout_marginTop="6dp"
|
||||
android:background="@drawable/round_edit_text"
|
||||
android:ems="10"
|
||||
android:text="@={viewmodel.topVal}"
|
||||
android:hint="insert value one"
|
||||
android:textColorHighlight="#608d91"
|
||||
android:inputType="numberDecimal"
|
||||
@@ -96,7 +95,6 @@
|
||||
android:layout_weight="7"
|
||||
android:background="@drawable/round_edit_text"
|
||||
android:ems="10"
|
||||
android:text="@={viewmodel.bottomVal}"
|
||||
android:hint="insert value two"
|
||||
android:textColorHighlight="#608d91"
|
||||
android:inputType="numberDecimal"
|
||||
|
||||
Reference in New Issue
Block a user