I am calling the API using retrofit in ApiClient Class. Where I am trying to store the output of successful login either message or responseBody into the output string. I tried using the output string as part of ViewModel Observer type too
But I CANNOT pass the value of output from AplClient to MainActivity
APICLIENT
...
package com.example.services.api
lateinit var service: ApiInterface
object ApiClient {
@JvmStatic
private val BASE_URL = GlobalConstants.SWAGGER
//private val sharedPrefClass = SharedPrefClass()
@JvmStatic
private var mApiInterface: ApiInterface? = null
var output = "Initializing"
// val sharedPrefClass: SharedPrefClass? = null
// @JvmStatic
// fun getApiInterface(): ApiInterface {
// return setApiInterface()
// }
@JvmStatic
fun setApiInterface() : String {
val platform = GlobalConstants.PLATFORM
var mAuthToken = GlobalConstants.SESSION_TOKEN
var companyId = GlobalConstants.COMPANY_ID
var phone = phone
var cCode = cCode
//Here a logging interceptor is created
//Here a logging interceptor is created
val logging = HttpLoggingInterceptor()
logging.setLevel(HttpLoggingInterceptor.Level.BODY)
//The logging interceptor will be added to the Http client
//The logging interceptor will be added to the http client
val httpClient = OkHttpClient.Builder()
httpClient.addInterceptor(logging)
//The Retrofit builder will have the client attached, in order to get connection logs
//The Retrofit builder will have the client attached, in order to get connection logs
val retrofit: Retrofit = Retrofit.Builder()
.client(httpClient.build())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.build()
service = retrofit.create<ApiInterface>(ApiInterface::class.java)
val call: Call<Tree> = service.post(phone, cCode, companyId, platform)
var model: Model
call.enqueue(object : Callback<Tree> {
override fun onResponse(
call: Call<Tree>, response: Response<Tree>)
{
Log.e(TAG, "Success")
if (!response.isSuccessful()) {
model = Model("Success", "91", "8884340404")
model.output += response.body().toString()
return;
}
}
override fun onFailure(
call: Call<Tree>,
t: Throwable
) {
Log.e(TAG, "Json/Network Error")
model = Model("Json/Network Error", "91", "8884340404")
model.output = "Json/Network Error"
// handle execution failures like no internet connectivity
}
})
return output
}
}
VIEWMODEL
package com.example.kotlinloginapi.viewModel
import androidx.databinding.Observable
import androidx.databinding.ObservableField
import androidx.lifecycle.MutableLiveData
class Model {
var output:String? = null
var cCode:String? = null
var phone: String? = null
constructor(output: String?, cCode: String?, phone: String?) {
this.output = output
this.cCode = cCode
this.phone = phone
}
}
...
MAINACTIVTY
...
package com.example.kotlinloginapi.ui.login
lateinit var textView: TextView
class MainActivity : AppCompatActivity() {
lateinit var mainBinding : ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
textView = findViewById<TextView>(R.id.textView)
val mApiService: ApiService<Tree>
val mApiClient = ApiClient
var model: Model
model = Model("Creating View", "91", "8884340404")
model.output = "Creating View"
Observable.just(setApiInterface())
.subscribe {
println(it)
textView!!.append(setApiInterface())}
// mainBinding.viewModel!!.output = "Creating View"
textView.append("\n" + model.output)
/*fun getLoginData(jsonObject : JsonObject?) {
if (jsonObject != null) {
val mApiService = ApiService<JsonObject>()
mApiService.get(
object : ApiResponse<JsonObject> {
override fun onResponse(mResponse : Response<JsonObject>) {
val loginResponse = if (mResponse.body() != null)
finish()
else {
output = mResponse.body().toString()
}
}
override fun onError(mKey : String) {
Toast.makeText(
applicationContext,
"Error",
Toast.LENGTH_LONG
).show()
}
}, ApiClient.getApiInterface().callLogin(jsonObject)
)
}
}*/
}
}
LOGINACTIVITY
package com.example.kotlinloginapi.ui.login
lateinit var cCode: String
lateinit var phone: String
class LoginActivity : AppCompatActivity() {
lateinit var loginBinding : ActivityLoginBinding
lateinit var eTcCode: EditText
lateinit var eTphone: EditText
private lateinit var loginViewModel: LoginViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
loginBinding = DataBindingUtil.setContentView(this, R.layout.activity_login)
eTcCode = findViewById<EditText>(R.id.etcCode)
eTphone = findViewById<EditText>(R.id.etPhone)
val login = findViewById<Button>(R.id.login)
val loading = findViewById<ProgressBar>(R.id.loading)
var model = Model("Binding Model", "91", "8884340404")
loginBinding.model = model
loginBinding.lifecycleOwner
loginViewModel = ViewModelProviders.of(this, LoginViewModelFactory())
.get(LoginViewModel::class.java)
loginViewModel.loginFormState.observe(this@LoginActivity, Observer {
val loginState = it ?: return@Observer
// disable login button unless both username / password is valid
login.isEnabled = loginState.isDataValid
if (loginState.usernameError != null) {
eTcCode.error = getString(loginState.usernameError)
}
if (loginState.passwordError != null) {
eTphone.error = getString(loginState.passwordError)
}
})
loginViewModel.loginResult.observe(this@LoginActivity, Observer {
val loginResult = it ?: return@Observer
loading.visibility = View.VISIBLE
if (loginResult.error != null) {
showLoginFailed(loginResult.error)
}
if (loginResult.success != null) {
updateUiWithUser(loginResult.success)
}
setResult(Activity.RESULT_OK)
//Complete and destroy login activity once successful
finish()
})
eTcCode.afterTextChanged {
loginViewModel.loginDataChanged(
eTcCode.text.toString(),
eTphone.text.toString()
)
}
eTphone.apply {
afterTextChanged {
loginViewModel.loginDataChanged(
eTcCode.text.toString(),
eTphone.text.toString()
)
}
setOnEditorActionListener { _, actionId, _ ->
when (actionId) {
EditorInfo.IME_ACTION_DONE ->
loginViewModel.login(
eTcCode.text.toString(),
eTphone.text.toString()
)
}
false
}
login.setOnClickListener {
loading.visibility = View.VISIBLE
loginViewModel.login(eTcCode.text.toString(), eTphone.text.toString())
}
}
}
private fun updateUiWithUser(model: LoggedInUserView) {
val welcome = getString(R.string.welcome)
val displayName = model.displayName
// TODO : initiate successful logged in experience
cCode = eTcCode.text.toString()
phone = eTphone.text.toString()
var intent = Intent(this, MainActivity::class.java)
startActivity(intent)
Toast.makeText(
applicationContext,
"$welcome $displayName",
Toast.LENGTH_LONG
).show()
}
private fun showLoginFailed(@StringRes errorString: Int) {
Toast.makeText(applicationContext, errorString, Toast.LENGTH_SHORT).show()
}
}
/**
* Extension function to simplify setting an afterTextChanged action to EditText components.
*/
fun EditText.afterTextChanged(afterTextChanged: (String) -> Unit) {
this.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(editable: Editable?) {
afterTextChanged.invoke(editable.toString())
}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
})
}
...
Ideally, I want to use binding observers but I am unable to pass the output of retrofit to MainActivity even without that.