Receiving null from getParcelableExtra() - android

I have a class category and i pass into the extra, the category clicked.
this worked in 6 screens but in the last one I'm receiving null
the activity where i put the extra
adapter.setOnItemClickListener { item, view ->
val categories = item as Categories
val intent = Intent(view.context, LearningFirstLibras::class.java)
intent.putExtra(CATEGORY_KEY, categories.category)
startActivity(intent)
}
the category
#Parcelize
class Category(
val name: String,
val imageURL: String,
val real_name: String,
val object_1_screen_libras_image: String,
val object_1_screen_libras_text: String,
val object_2_screen_libras_text: String,
val object_2_screen_libras_image: String,
val object_3_screen_libras_text: String,
val object_3_screen_libras_image: String,
val object_1_screen_asl_text: String,
val object_1_screen_asl_image: String,
val object_2_screen_asl_text: String,
val object_2_screen_asl_image: String,
val object_3_screen_asl_text: String,
val object_3_screen_asl_image: String,
val question: String,
val answer: String,
val alternative_1: String,
val alternative_2: String,
val alternative_3: String,
val alternative_4: String
) : Parcelable {
constructor() : this("", "", "", "", "",
"","","","",
"","","","",
"","","","","","",
"","")
}
the activity where i got null
class Quiz : AppCompatActivity() {
var categoryF:Category = Category()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_quiz)
categoryF = intent.getParcelableExtra(NewWordsActivity.CATEGORY_KEY)

Try it
Sending the Parcelable Using Bundle
val intent = Intent(this, ProfilePage::class.java)
var bundle = Bundle()
bundle.putParcelable(CATEGORY_KEY, categories.category)
intent.putExtra("myBundle",bundle)
startActivity(intent)
Recovering Parcelable
val bundle = intent.getBundleExtra("myBundle")
var categoryF = bundle.getParcelable<Category>(NewWordsActivity.CATEGORY_KEY) as Category

Related

how to get data from rest api using retrofit kotlin android

I am trying to get data from rest api using retrofit on Android app.
I am trying to reach the data structured below;
sections -> items -> venue -> id (Unique id of the venue)
sections -> items -> venue -> name (Name of the venue)
sections -> items -> venue -> short_description (Description of the venue)
I can reach to the sections but not the data under the section.
data class VenueModel(
val created: Created,
val expires_in_seconds: Int,
val filtering: Filtering,
val name: String,
val page_title: String,
val sections: List<Section>,
val show_large_title: Boolean,
val show_map: Boolean,
val sorting: SortingX,
val track_id: String
)
data class Section(
val items: List<Item>,
val link: LinkX,
val name: String,
val template: String,
val title: String
)
data class Item(
val description: String,
val filtering: FilteringX,
val image: Image,
val link: Link,
val overlay: String,
val quantity: Int,
val quantity_str: String,
val sorting: Sorting,
val template: String,
val title: String,
val track_id: String,
val venue: Venue
)
data class Venue(
val address: String,
val badges: List<Badge>,
val categories: List<Any>,
val city: String,
val country: String,
val currency: String,
val delivers: Boolean,
val delivery_price: String,
val delivery_price_highlight: Boolean,
val delivery_price_int: Int,
val estimate: Int,
val estimate_range: String,
val franchise: String,
val id: String,
val location: List<Double>,
val name: String,
val online: Boolean,
val price_range: Int,
val product_line: String,
val promotions: List<Any>,
val rating: Rating,
val short_description: String,
val show_wolt_plus: Boolean,
val slug: String,
val tags: List<String>
)
this is api service interface;
interface APIService {
#GET("v1/pages/restaurants?lat=60.170187&lon=24.930599")
fun getVenues(#Query("lat") locationLatitude: String, #Query("lon") locationLongitude: String) : Call<VenueModel>
}
And this is main activity;
class MainActivity : AppCompatActivity() {
var locationLatitude = "60.170187"
var locationLongitude = "24.930599"
lateinit var venueSearchListSection: List<Section>
lateinit var venueSearchListItem: List<Item>
lateinit var venueSearchListVenue: List<Venue>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
venueSearchListSection = ArrayList<Section>()
venueSearchListItem = ArrayList()
venueSearchListVenue = ArrayList()
fetchDataFromApi()
}
private fun fetchDataFromApi(){
//venue results from api
val retrofitVenueSearch = Retrofit.Builder()
.baseUrl("https://restaurant-api.wolt.com/")
.addConverterFactory(GsonConverterFactory.create()).build()
val apiVenueSearch = retrofitVenueSearch.create(APIService::class.java)
apiVenueSearch.getVenues(locationLatitude, locationLongitude).enqueue(object :
Callback<VenueModel> {
override fun onResponse(
call: Call<VenueModel>,
response: Response<VenueModel>
) {
venueSearchListSection = response.body()?.sections ?: venueSearchListSection
//I have the problem here. I can get the data in venueSearchListSection
//arraylist but I can not reach the data inside it.
}
override fun onFailure(call: Call<VenueModel>, t: Throwable) {
t.message?.let { Log.e("venue", it) }
}
})
}
}
Thanks for your helps in advance.

Parameter specified as non-null is null error in Room Database

Here is my entity class:
#Entity
data class User(
#PrimaryKey
#Json(name = "id") val userId: String,
#Json(name = "login") val userName: String,
#Json(name = "avatar_url") val userAvatar: String,
val profile: Profile? = null
) : Serializable
Here is my Profile data class
data class Profile(
val avatar_url: String,
val bio: String,
val blog: String,
val company: Any,
val created_at: String,
val email: Any,
val events_url: String,
val followers: Int,
val followers_url: String,
val following: Int,
val following_url: String,
val gists_url: String,
val gravatar_id: String,
val hireable: Boolean,
val html_url: String,
val id: Int,
val location: String,
val login: String,
val name: String,
val node_id: String,
val organizations_url: String,
val public_gists: Int,
val public_repos: Int,
val received_events_url: String,
val repos_url: String,
val site_admin: Boolean,
val starred_url: String,
val subscriptions_url: String,
val twitter_username: Any,
val type: String,
val updated_at: String,
val url: String
) : Serializable
but every time I try to insert data into the table I am getting the error, how can I insert null data object in table while using room database?
The issue here is that Room doesn't know how to insert attribute of type Profile to the table.
The simple solution would be to use a type converter. Something like the following:
class DatabaseConverters {
#TypeConverter
fun toProfile(profileJson: String): Profile? {
return <Create a Profile object out of a JSON string>
}
#TypeConverter
fun fromProfile(profile: Profile?): String {
return <JSON string representation of Profile object>
}
}
In your case - you can use "" (empty string) when Profile is null.
More info about converters: Here

How my Model Class should looks like for a retrofit request in Kotlin?

I'm trying to create a request using Retrofit2 in Kotlin and my Json data looks like this:
{
"actionRights": [
{
"hasArticlePriceChangeRights": false,
"hasStockLevelViewRights": false
}
],
"stats": {
"errors": 12,
"warnings": 21,
"outOfOrder": 58,
"running": 42
},
"markers": []
}
I need to get the "stats" data from my response.
How is my model class look like? I tried something but I get this error.
Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
EDIT: I created this ModelClass and I'm still getting this error:
Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
data class StatsModel(
#SerializedName("actionRights") val actionRights : List<ActionRights>,
#SerializedName("stats") val stats : Stats,
#SerializedName("markers") val markers : List<Markers>
) {
data class ActionRights (
#SerializedName("hasArticlePriceChangeRights") val hasArticlePriceChangeRights : Boolean,
#SerializedName("hasStockLevelViewRights") val hasStockLevelViewRights : Boolean
)
data class Stats (
#SerializedName("errors") val errors : Int,
#SerializedName("warnings") val warnings : Int,
#SerializedName("outOfOrder") val outOfOrder : Int,
#SerializedName("running") val running : Int
)
data class Markers (
#SerializedName("deviceGuid") val deviceGuid : String,
#SerializedName("lat") val lat : Double,
#SerializedName("lng") val lng : Double,
#SerializedName("title") val title : Int,
#SerializedName("city") val city : String,
#SerializedName("street") val street : Int,
#SerializedName("serialNumber") val serialNumber : Int,
#SerializedName("LastStatusMessageDateTime") val lastStatusMessageDateTime : String,
#SerializedName("LastStatusMessageBitSet_0_63") val lastStatusMessageBitSet_0_63 : Int,
#SerializedName("LastStatusMessageBitSet_64_127") val lastStatusMessageBitSet_64_127 : Int,
#SerializedName("ActionsStatus") val actionsStatus : Int,
#SerializedName("SpareColumn1") val spareColumn1 : String,
#SerializedName("SpareColumn2") val spareColumn2 : String,
#SerializedName("SpareColumn3") val spareColumn3 : String,
#SerializedName("SpareColumn4") val spareColumn4 : String,
#SerializedName("SpareColumn5") val spareColumn5 : String,
#SerializedName("SpareColumn6") val spareColumn6 : String,
#SerializedName("SpareColumn7") val spareColumn7 : String,
#SerializedName("SpareColumn8") val spareColumn8 : String,
#SerializedName("SpareColumn9") val spareColumn9 : String,
#SerializedName("SpareColumn10") val spareColumn10 : String,
#SerializedName("EstimatedDeliveryDateTime") val estimatedDeliveryDateTime : String,
#SerializedName("IpAddress") val ipAddress : String,
#SerializedName("Active") val active : Int,
#SerializedName("ParentAreaGuid") val parentAreaGuid : String,
#SerializedName("AreaGuid") val areaGuid : String,
#SerializedName("TariffGroupGuid") val tariffGroupGuid : String,
#SerializedName("DeviceType") val deviceType : String,
#SerializedName("EstimateArticleName") val estimateArticleName : String,
#SerializedName("EstimateArticleGuid") val estimateArticleGuid : String,
#SerializedName("lastCoinboxExchange") val lastCoinboxExchange : String,
#SerializedName("lastStatusUpdateTime") val lastStatusUpdateTime : String,
#SerializedName("reportDateTime") val reportDateTime : String,
#SerializedName("hasFinancialInfo") val hasFinancialInfo : Boolean,
#SerializedName("ticketsSold") val ticketsSold : Int,
#SerializedName("cash") val cash : Int,
#SerializedName("cashless") val cashless : Int,
#SerializedName("hasStockLevel") val hasStockLevel : Boolean,
#SerializedName("hasArticlePrices") val hasArticlePrices : Boolean,
#SerializedName("EstDeliveryDays") val estDeliveryDays : String,
#SerializedName("hasOther") val hasOther : Boolean,
#SerializedName("hasOutOfOrder") val hasOutOfOrder : Boolean,
#SerializedName("hasWarning") val hasWarning : Boolean,
#SerializedName("hasError") val hasError : Boolean,
#SerializedName("flags") val flags : List<Flags>,
#SerializedName("actionState") val actionState : String,
#SerializedName("spareColumns") val spareColumns : List<SpareColumns>
)
data class Flags (
#SerializedName("ErrorLevel") val errorLevel : Int,
#SerializedName("ErrorFlag") val errorFlag : Int,
#SerializedName("Translation") val translation : String,
#SerializedName("BitPosition") val bitPosition : Int
)
data class SpareColumns (
#SerializedName("key") val key : String,
#SerializedName("value") val value : String
)
}
And I'm processing the response like this:
fun getStatusService(mandatorGuid: String, #Nullable statusCallbacks: ChartsCallbacks.StatsCallbacks) {
val mandatorItem = MandatorItem(mandatorGuid)
val guid: MutableMap<String, String> = HashMap()
guid["guid"] = mandatorItem.guid
var statusData: StatsModel.Stats
val call: Call<StatsModel> = createAPI().getStatus(mandatorItem.guid)
call.enqueue(object : Callback<StatsModel> {
override fun onFailure(call: Call<StatsModel>, t: Throwable) {
Log.i("TEST", "Status failure: $t")
}
override fun onResponse(call: Call<StatsModel>, response: Response<StatsModel>) {
if (response.isSuccessful) {
Log.i("TEST", "ITEM " + response.headers().toString())
statusData = response.body()!!.stats
Log.i("TEST", "ITEM $statusData")
statusCallbacks.onSuccess(statusData)
}
}
})
}
data class ActionRight(
val hasArticlePriceChangeRights: Boolean?=null,
val hasStockLevelViewRights: Boolean?=null
)
this is for state
data class Stats(
val errors:Int? = null,
val warnings? = null,
val outOfOrder? = null,
val running? = null
)
call this model into your retrofit you got only your state
data class StatsModel(
val actionRights: ArrrayList<ActionRight>?=null,
val markers: ArrrayList<Any>?=null,
val stats: Stats? = null)
Your main model:
data class MyModel(
val actionRights: List<ActionRight?>?,
val markers: List<Marker?>?,
val stats: Stats?
)
Your Sub Models:
data class ActionRight(
val hasArticlePriceChangeRights: Boolean?,
val hasStockLevelViewRights: Boolean?
)
data class Marker(
val test1: Int?,
val test2: String?
)
data class Stats(
val errors: Int?,
val outOfOrder: Int?,
val running: Int?,
val warnings: Int?
)
I create a fake Marker class because I don't know your full json data.
You should modelling Marker class for according your json data. You can call MyModel class from retrofit.
Edit Response (Only parse Stats class)
This class represent parse only Stats class, you can call from retrofit. #JsonIgnoreProperties should ignore other data.
#JsonIgnoreProperties(ignoreUnknown = true)
data class MyModel(
#JsonProperty("stats")
val stats: Stats?
)
#JsonIgnoreProperties(ignoreUnknown = true)
data class Stats(
#JsonProperty("errors")
val errors: Int?,
#JsonProperty("outOfOrder")
val outOfOrder: Int?,
#JsonProperty("running")
val running: Int?,
#JsonProperty("warnings")
val warnings: Int?
)
Note: The code use Jackson library.
implementation 'com.squareup.retrofit2:converter-jackson:2.5.0'

How can I join three list in one object in Kotlin

I'm trying to join three object list in one object with kotlin. But I don't know how to do it...
Some help will be appreciate.
This is my data class:
data class User(
val address: Address,
val company: Company,
val email: String,
val id: Int,
val name: String,
val phone: String,
val username: String,
val website: String
)
data class Post(
val body: String,
val id: Int,
val title: String,
val userId: Int
)
data class Comment(
val body: String,
val email: String,
val id: Int,
val name: String,
val postId: Int
)
That I want to do is get one object like this if possible:
data class PostJoin(body: String, id: Int, title; String, user: User, comments: List<Comment>)
This is that I'm trying to do it, only can mix two objects but no how I want.
val postUsers = post.joinBy(users) { (post,user) -> post.userId == user.id }
.map { PostViewModel(post = it.first, user = it.second) }
private inline fun <T : Any, U : Any> List<T>.joinBy(collection: List<U>, filter: (Pair<T, U>) -> Boolean): List<Pair<T, List<U>>> = map { t ->
val filtered = collection.filter { filter(Pair(t, it)) }
Pair(t, filtered)
}
Something like this might work:
val posts: List<Post>
val users: List<User>
val comments: List<Comment>
// initialize lists
...
val joinedPosts = posts.fold(ArrayList<PostJoin>()) { joinedPosts, post ->
val postComments = comments.filter { it.postId == post.id }
val user = users.first { it.id == post.userId }
joinedPosts.add(PostJoin(post.body, post.id, post.title, user, postComments))
joinedPosts
}
Seems to work for me: Try it online!. Though I did give a pretty lazy input.

getting weather results from json (kotlin android)

I'm trying to get some results from json but i have a problem.When i have only this line of code it works and i can get the temperature
var main: TemperatureData? = null
but i want also to get more values from my json so i insert this line of code
var weather: WeatherDataJson? = null
When i'm adding the second line it doesn't fetch any data(it even stops fetching the var main:... data)
This is my weather data class
class WeatherData {
var main: TemperatureData? = null
var weather: WeatherDataJson? = null
}
here is my interface class
interface ApiInterface {
#GET("data/2.5/weather?q=Prague")
fun getWeatherData(#Query("appid") appId: String)
: Call<WeatherData>
}
My TemperatureData class
data class TemperatureData(var temp: String)
And my WeatherDataJson class
data class WeatherDataJson(var description:String)
In my mainclass i have a function to show the json into my screen but i can't load the "var weather..."
Here is the function
private fun getTemperatureData(repository: Repository) {
repository.getApiInterface()
.getWeatherData("4cf7f6610d941a1ca7583f50e7e41ba3")
.enqueue(object : Callback<WeatherData> {
override fun onFailure(call: Call<WeatherData>?, t: Throwable?) {
t?.printStackTrace()
}
override fun onResponse(call: Call<WeatherData>?, response: Response<WeatherData>?) {
val weatherData: WeatherData? = response?.body()
weatherData?.let {
it.main?.let {
tempText.text = it.temp
}
it.weather?.let{
weatherTextFromApi.text=it.description
}
}
}
})
}
On the description is says unresolved reference description
If you use openweathermap api declare those data classes
data class WeatherData(
#SerializedName("coord") val coord: Coord,
#SerializedName("weather") val weather: List<Weather>,
#SerializedName("base") val base: String,
#SerializedName("main") val main: TemperatureData,
#SerializedName("visibility") val visibility: Int,
#SerializedName("wind") val wind: Wind,
#SerializedName("clouds") val clouds: Clouds,
#SerializedName("dt") val dt: Int,
#SerializedName("sys") val sys: Sys,
#SerializedName("id") val id: Int,
#SerializedName("name") val name: String,
#SerializedName("cod") val cod: Int
)
data class Sys(
#SerializedName("type") val type: Int,
#SerializedName("id") val id: Int,
#SerializedName("message") val message: Double,
#SerializedName("country") val country: String,
#SerializedName("sunrise") val sunrise: Int,
#SerializedName("sunset") val sunset: Int
)
data class Coord(
#SerializedName("lon") val lon: Double,
#SerializedName("lat") val lat: Double
)
data class TemperatureData(
#SerializedName("temp") val temp: Double,
#SerializedName("pressure") val pressure: Int,
#SerializedName("humidity") val humidity: Int,
#SerializedName("temp_min") val tempMin: Double,
#SerializedName("temp_max") val tempMax: Double
)
data class Weather(
#SerializedName("id") val id: Int,
#SerializedName("main") val main: String,
#SerializedName("description") val description: String,
#SerializedName("icon") val icon: String
)
data class Clouds(
#SerializedName("all") val all: Int
)
data class Wind(
#SerializedName("speed") val speed: Double,
#SerializedName("deg") val deg: Int
)
if you goal is get description from weather all you need will be
weatherData.weather.firstOrNull()?. description ?: ""
For getting url of icon
It is kind of tricky, you could get url from response but only url of icon.
val iconId = weatherData.weather.firstOrNull()?. description
val iconUrl = iconId?.let{"http://openweathermap.org/img/w/${it}.png"} ?: ""
After that you should use Glide library or Picasso for loading imageUrl to ImageView
See more about Glide here https://github.com/bumptech/glide
The server response from OpenWeatherMap is returning a JSON array, not a JSON object, for weather. Gson/Retrofit cannot automatically turn an array into a single Object, so you need to change your data class to hold a List (or use a custom Gson deserializer and manually grab the item you want from the array).
Example of what your top level class should be:
class WeatherData {
var main: TemperatureData? = null
var weather: List<WeatherDataJson>? = null
}

Categories

Resources