I'm creating an app where the user has to insert a serverurl in an EditText field, and that url should be the baseUrl of the retrofit-request. So, my code works as it should when i use a hardcoded baseurl, but the app crashes when I try to pass the value from the Edittext to the baseUrl.
Thats how I tried to pass the value:
object NetworkLayer {
var newUrl: String = ""
val retrofit: Retrofit
get() = Retrofit.Builder()
.baseUrl(newUrl)
.addConverterFactory(GsonConverterFactory.create())
.build()
val myApi: MyApi by lazy {
retrofit.create(MyApi::class.java)
}
val apiClient = ApiClient(myApi)
}
and in my MainActivity:
var serverUrl = binding.et1.text.toString()
button.setOnClickListener {
NetworkLayer.newUrl = serverUrl
viewModel.getServerInformation(headerValue)
}
I get this error message: Error message: Caused by: java.lang.IllegalArgumentException: Expected URL scheme 'http' or 'https' but no scheme was found for.
So probably retrofit uses the empty "" string for the request. Somehow I should send the information to retrofit that when clicking the button the url from the Edittext (et1) is the baseUrl. When I use a seperate class (f.e. class Constants, with a companion object with a const val baseUrl = "hardcoded url") it works also. Can I create a function to inform the retrofit client to use the Edittext as baseUrl and declare it in the onClickListener? or could it be a way to create the retrofit client in a class instead of an object? (using url: String as parameter in the class and adding the edittext as argument in the MainActivity?) Sadly the @Url annotation for Retrofit doesn't work as I have to use also @Header and @Query in the different requests.
Or is there a compeletey different way for doing this?
Hopefully there is someone who can help me.
I managed to solve it, the only thing I had to change was: val url = binding.etServerUrl.text instead of val url = binding.etServerUrl.text.toString()
and when calling the function on button click I added the toString() to the url argument. When I try to add the toString() to the val url as I always did before it doesn't work, anyone can tell me why?
Here is an example how I use it (I changed the Retrofit client a bit to my first version in the question). So finally I can go ahead with my app, as I was blocked now for a few weeks with this.. :-)
object RetrofitClient{
var retrofitService: MyApi? = null
fun getInstance(url: String): MyApi{
if (retrofitService == null) {
val retrofit = Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build()
retrofitService = retrofit.create(MyApi::class.java)
}
return retrofitService!!
}
}
I changed the retrofitclient a bit, but it wors Then in the repository:
class MainRepository (){
suspend fun getToken(cookie: String, url: String): TokenResponse? {
val request = RetrofitClient.getInstance(url).getToken(cookie)
if (request?.isSuccessful!!) {
return request.body()!!
}
return null
}
}
Viewmodel:
class SharedViewModel() : ViewModel() {
private val repository = MainRepository()
private val _getTokenLiveData = MutableLiveData<TokenResponse>()
val getTokenLiveData: LiveData<TokenResponse> = _getTokenLiveData
fun getToken(cookie: String, url: String) {
viewModelScope.launch {
val response = repository.getToken(cookie, url)
_getTokenLiveData.postValue(response)
}
}
}
And finally the MainActivity:
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
val viewModel: SharedViewModel by lazy {
ViewModelProvider(this)[SharedViewModel::class.java]
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater) //initializing the binding class
setContentView(binding.root)
val url = binding.etServerUrl.text
val headerValue = binding.etMac.text.toString()
val button = binding.button
val textView = binding.textView
button.setOnClickListener {
viewModel.getToken(headerValue, url = url.toString())
}
viewModel.getTokenLiveData.observe(this) { response ->
if (response == null) {
Toast.makeText(this@MainActivity, "Fehlerhaft", Toast.LENGTH_SHORT).show()
return@observe
}
textView.text = response.js.token
}
}
}