0

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.

Shalu T D
  • 3,921
  • 2
  • 26
  • 37

1 Answers1

0

I moved the enqueue call to main activity which solved the problem. Now I can call text views. Will try to achieve this without moving and live data in future.