Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert RetrofitCallback to Kotlin and some refactoring #11

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith



@LargeTest
@RunWith(AndroidJUnit4::class)
class ConsentDetailsFragmentTest{
Expand Down
1 change: 0 additions & 1 deletion app/src/main/java/in/projecteka/jataayu/module/Modules.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import `in`.projecteka.jataayu.user.account.repository.UserAccountsRepositoryImp
import `in`.projecteka.jataayu.user.account.viewmodel.UserAccountsViewModel
import okhttp3.ResponseBody
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.core.qualifier.named
import org.koin.dsl.module
import retrofit2.Converter
import retrofit2.Retrofit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ package `in`.projecteka.jataayu.network.utils
import androidx.lifecycle.MutableLiveData
import retrofit2.Call

fun <T> Call<T>.observeOn(mutableLiveData: MutableLiveData<T>, responseCallback: ResponseCallback) {
fun <T> Call<T>.observeOn(mutableLiveData: MutableLiveData<T?>, responseCallback: ResponseCallback) {
enqueue(object : RetrofitCallback<T>(responseCallback) {
override fun observableLiveData(): MutableLiveData<T> {
override fun observableLiveData(): MutableLiveData<T?> {
return mutableLiveData
}
})
}

fun <T> Call<T>.observeOn(mutableLiveData: MutableLiveData<T>) {
fun <T> Call<T>.observeOn(mutableLiveData: MutableLiveData<T?>) {
enqueue(object : RetrofitCallback<T>() {
override fun observableLiveData(): MutableLiveData<T> {
override fun observableLiveData(): MutableLiveData<T?> {
return mutableLiveData
}
})
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package `in`.projecteka.jataayu.network.utils

import `in`.projecteka.jataayu.network.model.Error
import `in`.projecteka.jataayu.network.model.ErrorResponse
import androidx.lifecycle.MutableLiveData
import com.google.gson.Gson
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.net.HttpURLConnection.HTTP_FORBIDDEN
import java.net.HttpURLConnection.HTTP_UNAUTHORIZED

private const val DEFAULT_ERROR_CODE = -1
private const val ERROR_CODE_UNAUTHORIZED = 1017

abstract class RetrofitCallback<T> : Callback<T?> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not required to mark generic Optional. While casting, it will anyway become an optional.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generics enforced me to make it nullable. But I didn't put much effort to remove that nullable part. Pls remove it if not required.

private var responseCallback: ResponseCallback? = null

constructor()

constructor(responseCallback: ResponseCallback?) {
this.responseCallback = responseCallback
}

protected abstract fun observableLiveData(): MutableLiveData<T?>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can instead make this a part of constructor, since that is the contract anyway

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, there are cases where I don't want a callback/progress bar. e.g. Search. It was kept optional for that only.

override fun onResponse(call: Call<T?>, response: Response<T?>) {
if (response.isSuccessful) {
if (responseCallback != null) responseCallback!!.onSuccess(response.body())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can use ?.let operator instead of null check or !!

if (response.body() != null) {
observableLiveData().value = response.body()
}
} else {
if (response.errorBody() != null && responseCallback != null) {
try {
val errorResponse: ErrorResponse = Gson()
.fromJson<ErrorResponse>(response.errorBody()!!.string(), ErrorResponse::class.java)
responseCallback!!.onFailure(errorResponse)
} catch (e: Exception) {
e.printStackTrace()
var errorCode = DEFAULT_ERROR_CODE
if (response.code() in arrayOf(HTTP_FORBIDDEN, HTTP_UNAUTHORIZED)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good way of checking :) +1

errorCode = ERROR_CODE_UNAUTHORIZED
}
responseCallback!!.onFailure(ErrorResponse(Error(errorCode, e.message!!)))
}
}
}
}

override fun onFailure(call: Call<T?>, t: Throwable) {
if (responseCallback != null) responseCallback!!.onFailure(t)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package `in`.projecteka.jataayu.network

import `in`.projecteka.jataayu.network.interceptor.UnauthorisedUserRedirectInterceptor
import android.content.Context
import android.content.Intent
import com.google.gson.JsonObject
import okhttp3.OkHttpClient
import okhttp3.mockwebserver.MockResponse
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import `in`.projecteka.jataayu.presentation.showErrorDialog
import `in`.projecteka.jataayu.presentation.ui.BaseActivity
import `in`.projecteka.jataayu.presentation.ui.fragment.BaseFragment
import `in`.projecteka.jataayu.util.extension.startActivityForResult
import `in`.projecteka.jataayu.util.sharedPref.*
import `in`.projecteka.jataayu.util.sharedPref.getPinCreated
import `in`.projecteka.jataayu.util.sharedPref.setPinCreated
import android.app.Activity
import android.content.Intent
import android.net.Uri
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,34 +81,40 @@ class ConfirmPinFragment : BaseDialogFragment(), OtpSubmissionClickHandler, OtpC
bundle.getString(PIN)?.let { pin ->
if (confirmedPin == pin) {
showProgressBar(true)
viewModel.createPinResponse.observe(this, Observer {
viewModel.createPinResponse.observe(this, Observer { payloadResource ->

when (it) {
is Loading -> showProgressBar(it.isLoading, getString(R.string.creating_pin))
when (payloadResource) {
is Loading -> showProgressBar(payloadResource.isLoading, getString(R.string.creating_pin))
is Success -> {
activity?.let {
it.setPinCreated(true)
activity?.let { fragmentActivity ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead just do activity?.setPinCreated() or activity?.setResult, activity?.setFinish(). let creates a scoped function, so might not be useful considering the observer below has to be moved out.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have just added existing logic inside .let everywhere. If the said change is required, it was required before also.

fragmentActivity.setPinCreated(true)
showProgressBar(true)
viewModel.userVerificationResponse.observe(this, Observer { userVerificationResponse ->
activity?.setConsentTempToken(userVerificationResponse.temporaryToken)
EventBus.getDefault().post(MessageEventType.USER_VERIFIED)
it.setResult(Activity.RESULT_OK)
it.finish()
})
viewModel.userVerificationResponse.observe(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be outside this observer. Nesting observers leads to reregistering of observers everytime the parent observer observes an emission

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch

this,
Observer { userVerificationResponse ->
userVerificationResponse?.temporaryToken?.let {
activity?.setConsentTempToken(it)
EventBus.getDefault().post(MessageEventType.USER_VERIFIED)
fragmentActivity.setResult(Activity.RESULT_OK)
fragmentActivity.finish()
}
})
viewModel.verifyUser(pin, this)

}
}
is PartialFailure -> {
context?.showAlertDialog(getString(R.string.failure), it.error?.message,
getString(android.R.string.ok))
context?.showAlertDialog(
getString(R.string.failure), payloadResource.error?.message,
getString(android.R.string.ok)
)
}
}
})
if (context?.getConsentPinCreationAPIintegrationStatus()!!){
if (context?.getConsentPinCreationAPIintegrationStatus()!!) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can write this as if(context?.getConsentPinCreationAPIintegrationStatus() == true){...} to remove the force unwrapping

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

== true why? It will anyway go inside if it's true. Instead we can extract out the variable outside so it is unwrapped only once. But it's just one occurrence.

Copy link
Contributor

@rajivrajan rajivrajan Apr 3, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you have a boolean that is nullable and you need to check it, rather than !! force unwrapping or using the let block, you can evaluate that against a true / false value.

context?.getConsentPinCreationAPIintegrationStatus() gives a Boolean? because context is nullable here. if you don't want to force unwrap, you could write this as
context?.getConsentPinCreationAPIintegrationStatus()?.let { if(it){...}}
or
if(context?.getConsentPinCreationAPIintegrationStatus() == true){...}
This doesn't always evaluate true because
if the value is null, null != true.
if the value is false, false == true
if the value is true, true == true

showProgressBar(true)
viewModel.createPin(confirmedPin)
} else{
} else {
activity?.let {
it.setResult(Activity.RESULT_OK)
it.finish()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,10 @@ class UserVerificationFragment : BaseDialogFragment(), OtpSubmissionClickHandler

private fun initObservers() {
viewModel.userVerificationResponse.observe(this, Observer { it ->
context?.setConsentTempToken(it.temporaryToken)
EventBus.getDefault().post(MessageEventType.USER_VERIFIED)
it?.temporaryToken?.let {
context?.setConsentTempToken(it)
EventBus.getDefault().post(MessageEventType.USER_VERIFIED)
}
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import androidx.lifecycle.ViewModel

class UserVerificationViewModel(private val userVerificationRepository: UserVerificationRepository) : ViewModel() {
internal var createPinResponse = PayloadLiveData<Void>()
internal var userVerificationResponse = liveDataOf<UserVerificationResponse>()
internal var userVerificationResponse = liveDataOf<UserVerificationResponse?>()

fun createPin(pin: String) {
createPinResponse.fetch(userVerificationRepository.createPin(pin))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class PatientAccountsFragment : BaseFragment(), ItemClickCallback, PatientAccoun
viewModel.linkAccountsResponse.observe(this, linkAccountsObserver)
}

private val linkAccountsObserver = Observer<LinkAccountsResponse> { _ ->
private val linkAccountsObserver = Observer<LinkAccountsResponse?> { _ ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try to remove optionals in generics.

(activity as ProviderActivity).showVerifyOtpScreen()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,11 @@ class ProviderSearchFragment : BaseFragment(), ItemClickCallback, TextWatcherCal
private lateinit var selectedProvider : ProviderInfo
private lateinit var providersList: ProviderSearchAdapter

private val providersObserver = Observer<List<ProviderInfo>> { providerNames ->
providersList.updateData(lastQuery, providerNames)
showNoResultsFoundView(providerNames.isEmpty())
private val providersObserver = Observer<List<ProviderInfo>?> { providerNames ->
providerNames?.let {
providersList.updateData(lastQuery, it)
showNoResultsFoundView(it.isEmpty())
}
}

private val patientAccountsObserver =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class VerifyOtpFragment : BaseFragment(),
setTitle(R.string.verification)
}

private val observer = Observer<SuccessfulLinkingResponse> {
private val observer = Observer<SuccessfulLinkingResponse?> {
eventBus.post(MessageEventType.ACCOUNT_LINKED)
activity?.setResult(RESULT_OK)
activity?.finish()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ import `in`.projecteka.jataayu.util.extension.liveDataOf
import androidx.lifecycle.ViewModel

class ProviderSearchViewModel(private val providerRepository: ProviderRepository) : ViewModel() {
val providers = liveDataOf<List<ProviderInfo>>()
val providers = liveDataOf<List<ProviderInfo>?>()
var providersList = emptyList<ProviderInfo>()
val patientDiscoveryResponse = liveDataOf<PatientDiscoveryResponse>()
val linkAccountsResponse = liveDataOf<LinkAccountsResponse>()
val successfulLinkingResponse = liveDataOf<SuccessfulLinkingResponse>()
val patientDiscoveryResponse = liveDataOf<PatientDiscoveryResponse?>()
val linkAccountsResponse = liveDataOf<LinkAccountsResponse?>()
val successfulLinkingResponse = liveDataOf<SuccessfulLinkingResponse?>()

internal var selectedProviderName = String.EMPTY

Expand All @@ -35,7 +35,7 @@ class ProviderSearchViewModel(private val providerRepository: ProviderRepository

fun linkPatientAccounts(listCareContexts: List<CareContext>, responseCallback: ResponseCallback) {

var linkedAccounts = ArrayList<CareContext>()
val linkedAccounts = ArrayList<CareContext>()

listCareContexts.forEach {
if (it.contextChecked){
Expand All @@ -45,11 +45,11 @@ class ProviderSearchViewModel(private val providerRepository: ProviderRepository

val discoveryResponse = patientDiscoveryResponse.value
val selectedAccountsResponse = PatientDiscoveryResponse(Patient(discoveryResponse?.patient?.referenceNumber!!,
discoveryResponse.patient.display, linkedAccounts, discoveryResponse.patient?.matchedBy!!),
discoveryResponse.patient.display, linkedAccounts, discoveryResponse.patient.matchedBy),
discoveryResponse.transactionId)


providerRepository.linkPatientAccounts(selectedAccountsResponse!!).observeOn(linkAccountsResponse, responseCallback)
providerRepository.linkPatientAccounts(selectedAccountsResponse).observeOn(linkAccountsResponse, responseCallback)
}

fun verifyOtp(referenceNumber: String, otp: Otp, responseCallback: ResponseCallback) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package `in`.projecteka.jataayu.user.account.ui.fragment


import `in`.projecteka.jataayu.core.model.CreateAccountRequest
import `in`.projecteka.jataayu.core.model.CreateAccountResponse
import `in`.projecteka.jataayu.network.model.ErrorResponse
import `in`.projecteka.jataayu.network.utils.ResponseCallback
import `in`.projecteka.jataayu.presentation.callback.DateTimeSelectionCallback
Expand Down Expand Up @@ -88,10 +87,12 @@ class CreateAccountFragment : BaseFragment(),
if (validateFields()) {
showProgressBar(true)
viewModel.createAccountResponse.observe(this,
Observer<CreateAccountResponse> {
context?.setAuthToken(viewModel.getAuthTokenWithTokenType(it))
activity?.setResult(Activity.RESULT_OK)
activity?.finish()
Observer {
it?.let {
context?.setAuthToken(viewModel.getAuthTokenWithTokenType(it))
activity?.setResult(Activity.RESULT_OK)
activity?.finish()
}
})
viewModel.createAccount(this, getCreateAccountRequest())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,25 @@ class UserAccountsFragment : BaseFragment(), ItemClickCallback, ResponseCallback
private var compositeDisposable = CompositeDisposable()
private val eventBusInstance = EventBus.getDefault()

private val observer = Observer<LinkedAccountsResponse> {
binding.linkedPatient = it.linkedPatient
private val observer = Observer<LinkedAccountsResponse?> {
it?.let { binding.linkedPatient = it.linkedPatient }
getUserAccounts()
}

private val profileObserver = Observer<MyProfile> {
context?.setPinCreated(it.hasTransactionPin)
it.verifiedIdentifiers.forEach { identifier ->
if (identifier.type == VERIFIED_IDENTIFIER_MOBILE) {
activity?.setMobileIdentifier(identifier.value)
private val profileObserver = Observer<MyProfile?> {
it?.let {
context?.setPinCreated(it.hasTransactionPin)
it.verifiedIdentifiers.forEach { identifier ->
if (identifier.type == VERIFIED_IDENTIFIER_MOBILE) {
activity?.setMobileIdentifier(identifier.value)
}
}
}
}

companion object {
fun newInstance() = UserAccountsFragment()
private val VERIFIED_IDENTIFIER_MOBILE = "MOBILE"
private const val VERIFIED_IDENTIFIER_MOBILE = "MOBILE"
}

override fun onCreateView(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import androidx.lifecycle.ViewModel
import java.util.regex.Pattern

class UserAccountsViewModel(private val repository: UserAccountsRepository) : ViewModel() {
var linkedAccountsResponse = liveDataOf<LinkedAccountsResponse>()
var createAccountResponse = liveDataOf<CreateAccountResponse>()
var myProfileResponse = liveDataOf<MyProfile>()
var linkedAccountsResponse = liveDataOf<LinkedAccountsResponse?>()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can be made immutable

var createAccountResponse = liveDataOf<CreateAccountResponse?>()
var myProfileResponse = liveDataOf<MyProfile?>()

fun getUserAccounts(responseCallback: ResponseCallback) {
repository.getUserAccounts().observeOn(linkedAccountsResponse, responseCallback)
Expand Down
Loading