I try to recover the data of a player with the league of legends API however the response to my request is always null and those without an error message in my logcat.
here is my retrofit call:
public interface LolApiService {
#GET("summoners/by-name/")
Call<SummonerData> getSummonerData (#Query("summonerName")String summonerName, #Query("key") String key);
}
here is my repository:
class LolApiRepository(val application: Application) {
val response = MutableLiveData<SummonerData>()
fun getSummonerID(summonerName: String, key: String): MutableLiveData<SummonerData> {
// val responseData = MutableLiveData<SummonerData>()
val retrofit = Retrofit.Builder()
.baseUrl("https://euw1.api.riotgames.com/lol/summoner/v4/")
.addConverterFactory(GsonConverterFactory.create())
.build()
val service = retrofit.create(LolApiService::class.java)
service.getSummonerData(summonerName, key).enqueue(object : Callback<SummonerData> {
override fun onFailure(call: Call<SummonerData>, t: Throwable) {
Toast.makeText(application, "Error wile accessing the API", Toast.LENGTH_SHORT)
.show()
}
override fun onResponse(call: Call<SummonerData>, resp: Response<SummonerData>) {
Log.d("LolApiRepository", "LolApiRepository:" + resp.body().toString())
if (resp.body() != null) {
Toast.makeText(application, "Success accessing the API", Toast.LENGTH_SHORT)
.show()
response.value = (resp.body() as SummonerData)
} else {
Log.d("LolApiRepository", "LolApiRepository:" + resp.errorBody().toString())
Toast.makeText(application, "Error wile accessing the API", Toast.LENGTH_SHORT)
.show()
}
}
})
return response
}
}
my data model in which I retrieve the result of my query:
class SummonerData {
#SerializedName("id")
#Expose
var id: String? = null
#SerializedName("accountId")
#Expose
var accountId: String? = null
#SerializedName("puuid")
#Expose
var puuid: String? = null
#SerializedName("name")
#Expose
var name: String? = null
#SerializedName("profileIconId")
#Expose
var profileIconId: Int? = null
#SerializedName("revisionDate")
#Expose
var revisionDate: Int? = null
#SerializedName("summonerLevel")
#Expose
var summonerLevel: Int? = null
}
the fragment in which I want to display the data:
class LolStatFragment : Fragment() {
private lateinit var mViewModel: LolApiViewModel
private val apiKey = "api_key=RGAPI-bb27988b-cbb1-4767-b18b-icar8e90c308"
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_lol_stat, container, false)
mViewModel = ViewModelProviders.of(this).get(LolApiViewModel::class.java)
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
summoner_search.setOnClickListener {
val summonerName = summoner_name.text.toString()
mViewModel.summonerIds(summonerName,apiKey).observe(viewLifecycleOwner,Observer<SummonerData>{
summoner_ID.text = it.id
Log.d("LolStatFragment", "LolStatFragment:" + it.id)
Toast.makeText(context, "zzzzzzzzz ${it.id}", Toast.LENGTH_SHORT).show()
})
}
}
}
here is the result of my retrofit request on a web browser:
{"id":"OR5-q4c9Mw3jKXcPZw2lXul0tT7eLf4dYNadYrGhQ9mG8-w","accountId":"gOb2ZjN51iRLnRmDJuR5GmfILqP3x-T3qfbKWaTZ9k3dYw","puuid":"9TgzR6qdI_X9Z6xFzV0nFndITN0LSGKKeJ5fol2Ii1a01l4duKvFwpYGJQvBeYkBLkvJc96Sr7DZMg","name":"Practice","profileIconId":4353,"revisionDate":1619525378251,"summonerLevel":209}
thank you to all those who will take the time to answer me !
PS:this is my first question on the forum, I hope to have been clear and to have asked my question correctly,If there's any detail that I left out for this question, feel free to ask.
I finally found the answer to my problem, the url of the network call was not formatted well. here is the code used to retrieve my call url api in my OnResponse method and compare it to that of the browser:
Log.d("LolApiRepository", "LolApiRepository:" + resp.toString())
this is what I had to change in my LolApiService interface :
public interface LolApiService {
#GET("summoners/by-name/{summonerName}?")
Call<SummonerData> getSummonerData (#Path("summonerName") String summonerName, #Query("api_key") String key);
}
Related
I followed everything carefully, step by step, but I can't find what the problem is.
Whenever I fill in the name of the movie I intend to search by, the app crashes and it says this:
java.lang.NullPointerException: response.body() must not be null
Does anyone have any idea? Here is the following code.
MovieList.kt
class MovieList {
val imdbID: String
val Title: String
val Year: String
val Plot: String
val Poster: String
constructor(imdbID: String, Title: String, Year: String, Plot: String, Poster: String) {
this.imdbID = imdbID
this.Title = Title
this.Year = Year
this.Plot = Plot
this.Poster = Poster
}
}
OMDbApi.kt
interface OMDbApi {
#GET("t={Title}")
fun getMovieByTitle(#Path("Title") Title: String): Call<MovieList>
}
OMDbApiClient.kt
class OMDbApiClient {
companion object{
private var omdbapi: OMDbApi? = null
fun getOMDbApi(): OMDbApi?{
if(omdbapi == null){
omdbapi = Retrofit.Builder()
.baseUrl("http://www.omdbapi.com/?&apikey=eb73867f")
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(OMDbApi::class.java);
}
return omdbapi
}
}
}
FirstFragment.kt
class FirstFragment : Fragment() {
private lateinit var omdbapiClient: OMDbApi
private lateinit var tvMovieTitle: TextView
private lateinit var ivImagePoster: ImageView
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_first, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
omdbapiClient = OMDbApiClient.getOMDbApi()!!
val movieId: EditText = view.findViewById<EditText>(R.id.TitleId)
tvMovieTitle = view.findViewById(R.id.MovieTitleId)
ivImagePoster = view.findViewById(R.id.MoviePosterId)
movieId.setOnEditorActionListener { v, actionId, event ->
if(actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_ACTION_NEXT){
val movietitle: String = movieId.text.toString()
searchMovieByTitle(movietitle)
true
}
else{
Toast.makeText(activity, "Error!", Toast.LENGTH_LONG).show()
false
}
}
}
private fun searchMovieByTitle(movietitle: String) {
omdbapiClient.getMovieByTitle(movietitle).enqueue(object : Callback<MovieList>{
override fun onResponse(call: Call<MovieList>?, response: Response<MovieList>) {
displayData(response.body())
Toast.makeText(activity, "Success!", Toast.LENGTH_LONG).show()
}
override fun onFailure(call: Call<MovieList>?, t: Throwable?) {
Toast.makeText(activity, "Error!", Toast.LENGTH_LONG).show()
}
})
}
private fun displayData(data: MovieList) {
tvMovieTitle.text = data.Title
Glide.with(this).load(data.Poster).into(ivImagePoster)
}
}
I think you are getting an error response and that's why the response.body() is null. You should be handling an error response gracefully, instead of expecting the body to always not be null, but that is another matter.
I think the following lines of code are at fault:
interface OMDbApi {
#GET("t={Title}")
fun getMovieByTitle(#Path("Title") Title: String): Call<MovieList>
}
The 'Title' should be a #Query parameter instead of a #Path parameter, because the &t= part in the API url is a query parameter. When it is a query parameter you also don't specify it as part of the path in #GET.
Your code would then become:
interface OMDbApi {
#GET("")
fun getMovieByTitle(#Query("t") title: String): Call<MovieList>
}
Do this change and see if you still get an error response. You might want to check the log in the 'Logcat' tab to see what error you are getting back from the API.
For that you might have to enable a higher logging level. This is done by adding a logging interceptor when building the Retrofit client.
// Build a http client with logging enabled
val client = OkHttpClient.Builder()
.addInterceptor(HttpLoggingInterceptor().apply {
// you can also use Level.BODY for even more log information
level = HttpLoggingInterceptor.Level.BASIC
})
.build()
omdbapi = Retrofit.Builder()
.client(client) // add this line to use your http client
.baseUrl("http://www.omdbapi.com/?&apikey=eb73867f")
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(OMDbApi::class.java);
The following code solved my problem.
interface OMDbApi {
#GET("?apikey=[your api key]&")
fun getMovieByTitle(#Query("t") Title: String): Call<MovieList>
}
I want to use coroutines in my project only when I use coroutines I get the error :Unable to invoke no-args constructor. I don't know why it's given this error. I am also new to coroutines.
here is my apiclient class:
class ApiClient {
val retro = Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
Here is my endpoint class:
#GET("v2/venues/search")
suspend fun get(
#Query("near") city: String,
#Query("limit") limit: String = Constants.limit,
#Query("radius") radius: String = Constants.radius,
#Query("client_id") id: String = Constants.clientId,
#Query("client_secret") secret: String = Constants.clientSecret,
#Query("v") date: String
): Call<VenuesMainResponse>
my Repository class:
class VenuesRepository() {
private val _data: MutableLiveData<VenuesMainResponse?> = MutableLiveData(null)
val data: LiveData<VenuesMainResponse?> get() = _data
suspend fun fetch(city: String, date: String) {
val retrofit = ApiClient()
val api = retrofit.retro.create(VenuesEndpoint::class.java)
api.get(
city = city,
date = date
).enqueue(object : Callback<VenuesMainResponse>{
override fun onResponse(call: Call<VenuesMainResponse>, response: Response<VenuesMainResponse>) {
val res = response.body()
if (response.code() == 200 && res != null) {
_data.value = res
} else {
_data.value = null
}
}
override fun onFailure(call: Call<VenuesMainResponse>, t: Throwable) {
_data.value = null
}
})
}
}
my ViewModel class:
class VenueViewModel( ) : ViewModel() {
private val repository = VenuesRepository()
fun getData(city: String, date: String): LiveData<VenuesMainResponse?> {
viewModelScope.launch {
try {
repository.fetch(city, date)
} catch (e: Exception) {
Log.d("Hallo", "Exception: " + e.message)
}
}
return repository.data
}
}
part of activity class:
class MainActivity : AppCompatActivity(){
private lateinit var venuesViewModel: VenueViewModel
private lateinit var adapter: HomeAdapter
private var searchData: List<Venue>? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val editText = findViewById<EditText>(R.id.main_search)
venuesViewModel = ViewModelProvider(this)[VenueViewModel::class.java]
venuesViewModel.getData(
city = "",
date = ""
).observe(this, Observer {
it?.let { res ->
initAdapter()
rv_home.visibility = View.VISIBLE
adapter.setData(it.response.venues)
searchData = it.response.venues
println(it.response.venues)
}
})
this is my VenuesMainResponse data class
data class VenuesMainResponse(
val response: VenuesResponse
)
I think the no-args constructor warning should be related to your VenuesMainResponse, is it a data class? You should add the code for it as well and the complete Log details
Also, with Coroutines you should the change return value of the get() from Call<VenuesMainResponse> to VenuesMainResponse. You can then use a try-catch block to get the value instead of using enqueue on the Call.
Check this answer for knowing about it and feel free to ask if this doesn't solve the issue yet :)
UPDATE
Ok so I just noticed that it seems that you are trying to use the foursquare API. I recently helped out someone on StackOverFlow with the foursquare API so I kinda recognize those Query parameters and the Venue response in the code you provided above.
I guided the person on how to fetch the Venues from the Response using the MVVM architecture as well. You can find the complete code for getting the response after the UPDATE block in the answer here.
This answer by me has code with detailed explanation for ViewModel, Repository, MainActivity, and all the Model classes that you will need for fetching Venues from the foursquare API.
Let me know if you are unable to understand it, I'll help you out! :)
RE: UPDATE
So here is the change that will allow you to use this code with Coroutines as well.
Repository.kt
class Repository {
private val _data: MutableLiveData<mainResponse?> = MutableLiveData(null)
val data: LiveData<mainResponse?> get() = _data
suspend fun fetch(longlat: String, date: String) {
val retrofit = Retro()
val api = retrofit.retro.create(api::class.java)
try {
val response = api.get(
longLat = longlat,
date = date
)
_data.value = response
} catch (e: Exception) {
_data.value = null
}
}
}
ViewModel.kt
class ViewModel : ViewModel() {
private val repository = Repository()
val data: LiveData<mainResponse?> = repository.data
fun getData(longLat: String, date: String) {
viewModelScope.launch {
repository.fetch(longLat, date)
}
}
}
api.kt
interface api {
#GET("v2/venues/search")
suspend fun get(
#Query("ll") longLat: String,
#Query("client_id") id: String = Const.clientId,
#Query("client_secret") secret: String = Const.clientSecret,
#Query("v") date: String
): mainResponse
}
MainActivity.kt
private val viewModel by viewModels<ViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel.getData(
longLat = "40.7,-74",
date = "20210718" // date format is: YYYYMMDD
)
viewModel.data
.observe(this, Observer {
it?.let { res ->
res.response.venues.forEach { venue ->
val name = venue.name
Log.d("name ",name)
}
}
})
}
}
So I have an API endpoint (https://someEndpoint.com/someEndpoint/e-member?insert) with a body looks like below as shown in Postman:
{
"emember_id": "B3456",
"emember_name": "Darren Kent",
"emember_gender" : "L",
"emember_nohp" : "08123456799",
"emember_email" : "darreen#gmail.com",
"emember_address" : "Kost Mawar",
"emember_username" : "Dreen12",
"emember_password" : "Rahasia123456",
"emember_dob" : "1996-03-13T00:00:00.000Z",
"emember_lastupdate" : "0000-00-00T00:00:00.000Z"
}
And this with this Retrofit Client
object RetrofitClient {
private const val BASE_URL = "https://someEndpoint.com/someEndpoint/e-member?insert"
val instance: API by lazy{
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
retrofit.create(API::class.java)
}
}
With Interface:
interface API {
#POST("e-member?insert")
fun insertNewMember(#Body postedInformation : RegisterMemberRequestBody): Call<DefaultResponse>
}
And this is the Data class RegisterMemberRequestBody :
#Parcelize
data class RegisterMemberRequestBody(
#field:SerializedName("emember_id")
val ememberId: String? = null,
#field:SerializedName("emember_username")
val ememberUsername: String? = null,
#field:SerializedName("emember_gender")
val ememberGender: String? = null,
#field:SerializedName("emember_name")
val ememberName: String? = null,
#field:SerializedName("emember_password")
val ememberPassword: String? = null,
#field:SerializedName("emember_dob")
val ememberDob: String? = null,
#field:SerializedName("emember_nohp")
val ememberNohp: String? = null,
#field:SerializedName("emember_email")
val ememberEmail: String? = null,
#field:SerializedName("emember_lastupdate")
val ememberLastupdate: String? = null,
#field:SerializedName("emember_address")
val ememberAddress: String? = null
) : Parcelable
And this is the snippet from the fragment where I call the Retrofit Client
RetrofitClient.instance.insertNewMember(RegisterMemberRequestBody(
memberId,
username,
selectedGender,
fullName,
password,
selectedBirthday,
phoneNumber,
email,
lastUpdate,
address
)).enqueue(object: Callback<DefaultResponse> {
override fun onFailure(call: Call<DefaultResponse>, t: Throwable) {
Toast.makeText(activity as AppCompatActivity, "Request Failed!", Toast.LENGTH_LONG).show()
binding.registerFormRelativeLayout.visibility = View.VISIBLE
binding.progressBar.visibility = View.GONE
}
override fun onResponse(
call: Call<DefaultResponse>,
response: Response<DefaultResponse>
) {
Log.i("register", response.body().toString())
//renderSnackBar()
navigateToLoginPage()
}
})
The parameters (memberId,username ,selectedGender ,fullName ,password ,selectedBirthday ,phoneNumber ,email ,lastUpdate ,and address) for the Data class is picked from some EditTexts. These are the inputted value as I printed it in the LogCat :
However, When the function executed it shows in the Database (Firebase) as :
As you can see that some values are not inserted to the database. Any Idea how does this happen ? Is the anything I need to change ? If I miss to point out any detail feel free to ask.
Note: the fullname, address, phoneNumber, selectedBirthDay, and selectedGender is passed from different Fragment. But I'm sure 100% that there's nothing wrong with it since it shows up the desired value when I printed it in the current fragment.
**Edit: **
This is how the value fullname, address, phoneNumber, selectedBirthDay, and selectedGender are passed from other fragment to this fragment. This is the other snippet from the current fragment where the values are accepted
lateinit var binding: FragmentRegisterPart2Binding
lateinit var fullName: String
lateinit var selectedGender: String
lateinit var selectedBirthday: String
lateinit var phoneNumber: String
lateinit var address: String
lateinit var username: String
lateinit var password: String
lateinit var email: String
lateinit var confirmPassword: String
var memberId: String = ""
var lastUpdate: String = "0000-00-00T00:00:00.000Z"
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(
inflater,
R.layout.fragment_register_part2, container, false
)
val args = arguments?.let {
RegisterFragmentPart2Args.fromBundle(
it
)
}
if (args != null) {
fullName = args.fullName
address = args.address
phoneNumber = args.phoneNumber
selectedBirthday = args.selectedBirthday
selectedGender = args.selectedGender
}
binding.finishRegistrationButton.setOnClickListener {
validateInformationInput()
}
binding.progressBar.visibility = View.GONE
return binding.root
}
Edit
Things that I've tried are including :
Make sure the Retrofit Client Object does not have any problem since it successfully sent the data to the server
The passed values from the other fragment have no problem since it's showed up properly in the current fragment
The Interface has no problem since it sent some value successfully
The Data class structure has no problem since it successfully sent some value as well.
Now I'm wondering whether some attributes of the data class are not properly delcared or something like that. (I'm using an extension in Android studio that automatically convert the Copied Json body into a proper data class)
This happens because you created data class with some fields from EditTexts, when you do that others are set to null because you have put default value to be null. Also you have put all val on all fields, so when you create object with some values and some nulls you cant change those later from api
I am trying to get the response from https://www.reddit.com/r/popular/.rss and map to Kotlin POJO class in Android. But when I am logging that category's label value, getting null. For the title I am getting response value as popular links.
Here is entity class FeedX:-
#Root(name = "feed", strict = false)
class FeedX {
#set: Element(name = "category")
#get: Element(name = "category")
var category: Category? = null
val entry: List<Entry>? = null
val id: String? = null
val link: List<LinkX>? = null
#set: Element(name = "title")
#get: Element(name = "title")
var title: String? = null
val updated: String? = null
}
Category class:-
#Root(name = "category", strict = false)
class Category {
#set: Element(required = false, name = "_label")
#get: Element(required = false, name = "_label")
var _label: String? = null
val _term: String? = null
}
Here is Api Interface:-
interface FeedApi {
#GET("{type}/.rss")
fun getPopularFeeds(
#Path("type") type: String?
): Call<FeedX>?
}
Here is MainActivity:-
class MainActivity : AppCompatActivity() {
private val BASE_URL = "https://www.reddit.com/r/"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(SimpleXmlConverterFactory.create())
.build()
val service = retrofit.create(FeedApi::class.java)
service.getPopularFeeds("popular")?.enqueue(object : Callback<FeedX> {
override fun onFailure(call: Call<FeedX>, t: Throwable) {
Log.d("Response Failed", "${t.localizedMessage}")
}
override fun onResponse(call: Call<FeedX>, response: Response<FeedX>) {
if (response.isSuccessful) {
Log.d("Response Success", "${response.body()!!.title}") // for this I am getting value
Log.d("Response Success", "${response.body()!!.category?._label}") // always getting null value
} else {
Log.d("Response Failed jg", "${response.errorBody()}")
}
}
})
}
}
This is because title contains a value where category tag doesn't. See the difference below.
<title>popular links</title>
<category term="AskReddit" label="r/AskReddit"/>
As you can see category tag is self closing.
Here's the code where i am getting exception, tried various ways to implement context but nothing is working out.
class GrowthStoryFragment : Fragment() {
private val TAG = "GrowthStoryFragment"
companion object{
private var countryID = "1"
private var date = "MAT TY"
private var spec = "val"
private var businessUnitID = "2"
private var category = "Fresh Milk"
private var firstReportTypeId = "1" //fixed for growth story and share story
private var isGroup = "false" //fixed to false
}
private val backendApi = WinRetrofitHelper.winApiInstance()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_growth_story, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
getSpinnerResponse(businessUnitID, isGroup,firstReportTypeId)
getSuperRegionName(countryID, date,spec," ",businessUnitID, category, firstReportTypeId, isGroup)
growth_spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener{
override fun onNothingSelected(parent: AdapterView<*>?) {
}
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
val item = parent?.getItemAtPosition(position) as RespTwo
category = item.nameValue
Log.e(TAG,"Category name is: " + category)
getSuperRegionName(countryID, date,spec," ",businessUnitID, category, firstReportTypeId, isGroup)
}
}
}
private fun getSpinnerResponse(businessUnitID: String, isGroup: String, firstReportTypeId: String){
val request = backendApi.getCategoryBusinessUnit(businessUnitID, isGroup, firstReportTypeId)
request.enqueue(object : Callback<List<RespTwo>> {
override fun onFailure(call: Call<List<RespTwo>>?, t: Throwable?) {
Log.e(TAG, "Failure Super Region Name: ")
}
override fun onResponse(call: Call<List<RespTwo>>?, response: Response<List<RespTwo>>?) {
val myresponse = response?.body()
if (response?.body() != null && !response?.body()!!.isEmpty()) {
growth_spinner.adapter = GrowthSpinnerAdapter(response?.body())
Log.e(TAG, "Super Region Name: " + myresponse?.get(0)?.nameValue)
} else {
Toast.makeText(context!!.applicationContext, "Data Not Available!", Toast.LENGTH_LONG).show()
}
}
})
}
private fun getSuperRegionName(countryID: String, date: String, spec: String, superMarket: String,businessUnitID: String, category: String, firstReportTypeId: String, isGroup: String) {
val request = backendApi.getSuperRegion(countryID)
request.enqueue(object : Callback<List<RespMy>> {
override fun onFailure(call: Call<List<RespMy>>?, t: Throwable?) {
Log.e(TAG, "Failure Super Region Name: ")
}
override fun onResponse(call: Call<List<RespMy>>?, response: Response<List<RespMy>>?) {
val myresponse = response?.body()
if (response?.body() != null && !response?.body()!!.isEmpty()) {
getDataFromApi(countryID, date, spec, myresponse?.get(0)!!.nameValue, businessUnitID, category, firstReportTypeId, isGroup)
Log.e(TAG, "Super Region Name: " +countryID+" "+ date+" "+ spec+" "+ myresponse?.get(0)?.nameValue+" "+businessUnitID+" "+ category+" "+ firstReportTypeId+" " + isGroup+" ")
} else {
Toast.makeText(myApplicationContext, "Data Not Available!", Toast.LENGTH_LONG).show()
}
}
})
}
}
Please suggest something and i have heard a viewModel conversion of the requests made directly from fragments can fix this out but i don't know how to do that. Please help in either way.
Update:
Don't want to use static context here
ViewModel and Repository pattern is way to go.
You are doing async network call on Main thread, very bad idea.
For learning purposes - here is how to get your code working:
replace:
myApplicationContext = context!!.applicationContext
with:
myApplicationContext = requireContext()
or better - get rid of this variable entirely and just use requireContext() instead.
Toasts are usually applied to the activity rather than an generic context, and demanding the context via context!! should be avoided; it is optional for a reason. I would try the following after defining #string/data_not_available and #string/super_region_name_template in the string resource xml:
val body = response?.body()
if (body?.isNotEmpty() == true) {
growth_spinner.adapter = GrowthSpinnerAdapter(body)
Log.e(TAG, getString(R.string.super_region_name_template, body.get(0).nameValue)) // if applicable, use .first() over .get(0)
} else {
activity?.run {
Toast.makeText(this, getString(R.string.data_not_available), Toast.LENGTH_LONG).show()
}
}
try to use this
myApplicationContext: Context = this.context ?: return
then
Toast.makeText(myApplicationContext, "Data Not Available!",Toast.LENGTH_LONG).show()
for more details, you can see this link