We have a RecyclerView with a FlexboxLayoutManager witch throw an IndexOutOfBound on each scroll of the recyclerView.
FlexBox version: 2.0.1
Kotlin version: 1.4.30
Our code
C = EbookFlexController(this)
B.recycler.setItemViewCacheSize(10)
C.adapter.hasStableIds()
B.recycler.adapter = C.adapter
B.recycler.layoutManager = getFlexLayoutManager()
C represents the FlexBoxController
class FlexController(private val callbacks: Callbacks) : TypedEpoxyController<StreamCluster?>() {
interface Callbacks {
fun onAppClick(app: AppItem)
fun onAppLongClick(app: AppItem)
}
override fun buildModels(streamCluster: StreamCluster?) {
if (streamCluster == null) {
for (i in 1..8) {
add(
AppViewShimmerModel_()
.id(i)
)
}
} else {
streamCluster.appList.forEach { app ->
add(
AppViewModel_()
.id(app.packageName)
.click { _ ->
callbacks.onAppClick(app)
}
.longClick { _ ->
callbacks.onAppLongClick(app)
false
}
.app(app)
)
}
}
}
}
The stream Cluster
data class EbookStreamCluster(val id: String = UUID.randomUUID().toString()) {
var title: String = String()
var subtitle: String = String()
var category: String = String()
var url: String = String()
var ebookList: MutableList<EbookItem> = ArrayList()
var hasNext: Boolean = false
var isPaid:Boolean = false
var page: Int = 0
var type: Type = Type.CLUSTER
}
On firebase, we have this error:
Process: com.gara.store, PID: 3655
java.lang.IndexOutOfBoundsException: Index: 18, Size: 18
at java.util.ArrayList.get(ArrayList.java:437)
at com.google.android.flexbox.FlexboxLayoutManager.recycleFlexLinesFromStart(FlexboxLayoutManager.java:1335)
at com.google.android.flexbox.FlexboxLayoutManager.recycleByLayoutState(FlexboxLayoutManager.java:1315)
at com.google.android.flexbox.FlexboxLayoutManager.fill(FlexboxLayoutManager.java:1302)
at com.google.android.flexbox.FlexboxLayoutManager.handleScrollingMainOrientation(FlexboxLayoutManager.java:1974)
at com.google.android.flexbox.FlexboxLayoutManager.scrollVerticallyBy(FlexboxLayoutManager.java:1935)
at androidx.recyclerview.widget.RecyclerView.scrollStep(RecyclerView.java:1972)
at androidx.recyclerview.widget.RecyclerView$ViewFlinger.run(RecyclerView.java:5476)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1037)
at android.view.Choreographer.doCallbacks(Choreographer.java:845)
at android.view.Choreographer.doFrame(Choreographer.java:775)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1022)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7870)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
The same lib is used somewhere in the app and works without bugs. We don't know why with the exact same code, it is not working.
Please how could we do ?
Thanks
Related
I am building a Health application in which blood pressure monitor is used. I already paired so many BLE devices. I want to filter only particular device like Blood Pressure Monitor. I also did this in scan filter through like this
BloodPressurePairViewModel.kt
class BloodPressurePairViewModel : ViewModel() {
companion object {
private const val SCAN_PERIOD: Long = 10000 // For 1 minute scan
private const val UUID_MASK_STRING = "FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF"
private const val BLUETOOTH_PRESSURE_128_STRING = "00001810-0000-1000-8000-00805f9b34fb"
private const val BLUETOOTH_PRESSURE_MEASUREMENT_128_STRING = "00002A35-0000-1000-8000-00805f9b34fb"
}
var bluetoothLeScanner: BluetoothLeScanner? = null
var isBluetoothEnabled by mutableStateOf(false)
private set
val mLeDevices: MutableStateFlow<List<ScanResult>> = MutableStateFlow(emptyList())
var scanning: MutableStateFlow<Boolean> = MutableStateFlow(true)
private set
private val leScanCallback: ScanCallback = object : ScanCallback() {
override fun onScanResult(callbackType: Int, result: ScanResult) {
super.onScanResult(callbackType, result)
if (!mLeDevices.value.equals(result)) {
if (result.device?.name != null) {
if (checkDuplicateScanResult(mLeDevices.value, result)) {
mLeDevices.value += result
}
}
}
}
override fun onBatchScanResults(results: MutableList<ScanResult>?) {
super.onBatchScanResults(results)
logE("onBatchScanResults >> $results")
}
override fun onScanFailed(errorCode: Int) {
super.onScanFailed(errorCode)
logE("onScanFailed >> $errorCode")
}
}
fun setBluetoothEnable(newValue: Boolean) {
isBluetoothEnabled = newValue
}
fun startScan() {
viewModelScope.launch {
delay(SCAN_PERIOD)
scanning.value = false
bluetoothLeScanner?.startScan(scanFilters(), ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_POWER).build(), leScanCallback)
}
}
private fun scanFilters(): MutableList<ScanFilter> {
val scanFilterList = mutableListOf<ScanFilter>()
val parcelUuidMask = ParcelUuid.fromString(UUID_MASK_STRING)
val listItem = listOf(BLUETOOTH_PRESSURE_128_STRING, BLUETOOTH_PRESSURE_MEASUREMENT_128_STRING)
listItem.forEach {
val scanFilter = ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString(it), parcelUuidMask).build()
scanFilterList.add(scanFilter)
}
return scanFilterList
}
fun stopScan() {
bluetoothLeScanner?.stopScan(leScanCallback)
}
private fun checkDuplicateScanResult(value: List<ScanResult>, result: ScanResult): Boolean {
val checkDevice = value.count { it.device == result.device }
return checkDevice < 1
}
}
I used scanFilters() to find particular type of device like BPM. Now I want to filter according to my 128 bit string in my bonded device. I tried this piece of code from this stack overflow but it didn't work. I tried this piece of code
val getUuidsMethod: Method = BluetoothAdapter::class.java.getDeclaredMethod("getUuids", null)
val uuids = getUuidsMethod.invoke(bluetoothAdapter, null)
but it giving me error
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:526)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:516)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
Caused by: java.lang.NoSuchMethodException: parameter type is null
at java.lang.Class.getMethod(Class.java:2063)
at java.lang.Class.getDeclaredMethod(Class.java:2050)
at com.abc.app.bloodpressure.composables.PairScreenState.getPairedDevice(BloodPressurePairScreen.kt:176)
at com.abc.app.bloodpressure.composables.PairScreenState.<init>(BloodPressurePairScreen.kt:156)
at com.abc.app.bloodpressure.composables.BloodPressurePairScreenKt.rememberPairScreenState(BloodPressurePairScreen.kt:118)
at com.abc.app.bloodpressure.composables.BloodPressurePairScreenKt.BluetoothPairContentStateful(BloodPressurePairScreen.kt:66)
at com.abc.app.bloodpressure.composables.BloodPressurePairScreenKt.BluetoothPairContent(BloodPressurePairScreen.kt:52)
at com.abc.app.bloodpressure.composables.BluetoothRequestScreenKt$BluetoothRequestContent$1.invoke(BluetoothRequestScreen.kt:39)
at com.abc.app.bloodpressure.composables.BluetoothRequestScreenKt$BluetoothRequestContent$1.invoke(BluetoothRequestScreen.kt:35)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
Can you guys help me on this?
I am using sealed class to handle api response. I am trying some code but getting some error of serialization. I tried this solution as well but it not working. Can you guys help me out on this problem. I am new in serialization field.
import kotlinx.serialization.Serializable
sealed class ApiResponse<out T : Any> {
data class Success<out T : Any>(
val data: T?
) : ApiResponse<T>()
data class Error(
val exception: Throwable? = null,
val responseCode: Int = -1
) : ApiResponse<Nothing>()
fun handleResult(onSuccess: ((responseData: T?) -> Unit)?,onError: ((error: Error) -> Unit)?) {
when (this) {
is Success -> {
onSuccess?.invoke(this.data)
}
is Error -> {
onError?.invoke(this)
}
}
}
}
#Serializable
data class ErrorResponse(
val errorCode: Int,
val errorMessage: String
)
Api
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.request.*
import kotlinx.coroutines.flow.Flow
import kotlinx.serialization.Serializable
class KtorCountryApi(private val httpClient: HttpClient) {
suspend fun getCart(): Flow<ApiResponse<KtorCountriesResponse>> {
println("api call")
return httpClient.get {
url("https://shop-api.example-stg2.com/api/v1/address/country")
}.body()
}
}
#Serializable
data class KtorCountriesResponse(
val items: List<KtorCountry>? = null
)
#Serializable
data class KtorCountry(
val id: String? = null,
val isCurrentCountry: Boolean? = null,
var isoAlpha2Code: String? = null,
var name: String? = null,
var phonePrefix: String? = null,
val usesPerAreaShipping: Boolean? = null
)
Client
actual fun httpClient(config: HttpClientConfig<*>.() -> Unit) = HttpClient(OkHttp) {
config(this)
install(Logging) {
logger = Logger.SIMPLE
level = LogLevel.BODY
}
install(ContentNegotiation) {
json(Json {
prettyPrint = true
ignoreUnknownKeys = true
explicitNulls = false
})
}
engine {
config {
retryOnConnectionFailure(true)
connectTimeout(30, TimeUnit.SECONDS)
readTimeout(40, TimeUnit.SECONDS)
}
}
defaultRequest {
header("Client-Version", Platform().versionCode)
}
install(Auth) {
bearer {
loadTokens {
BearerTokens(tokenProvider.accessToken, "")
}
refreshTokens {
val response =
client.post("https://example-stg2.com/api/v1/session/refresh") {
markAsRefreshTokenRequest()
contentType(ContentType.Application.Json)
setBody(KtorSessionCommand(tokenProvider.refreshToken))
}
if (response.status == HttpStatusCode.Unauthorized) {
null
} else {
val ktorLoginResponse = response.body<KtorLoginResponse>()
ktorLoginResponse.accessToken?.let { ktorAccessToken ->
ktorAccessToken.accessToken?.let { accessToken ->
ktorAccessToken.refreshToken?.let { refreshToken ->
BearerTokens(accessToken, refreshToken)
}
}
}
}
}
}
}
}
Error
2022-04-22 10:50:28.614 8365-8365/com.example.app.dev E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.app.dev, PID: 8365
kotlinx.serialization.json.internal.JsonDecodingException: Polymorphic serializer was not found for missing class discriminator ('null')
JSON input: .....pping":false,"phonePrefix":"263","isCurrentCountry":false}]}
at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24)
at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:32)
at kotlinx.serialization.json.internal.PolymorphicKt.throwSerializerNotFound(Polymorphic.kt:76)
at kotlinx.serialization.json.internal.PolymorphicKt.decodeSerializableValuePolymorphic(Polymorphic.kt:66)
at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:36)
at kotlinx.serialization.json.Json.decodeFromString(Json.kt:100)
at io.ktor.serialization.kotlinx.KotlinxSerializationConverter.deserialize(KotlinxSerializationConverter.kt:55)
at io.ktor.client.plugins.contentnegotiation.ContentNegotiation$Plugin$install$2.invokeSuspend(ContentNegotiation.kt:135)
at io.ktor.client.plugins.contentnegotiation.ContentNegotiation$Plugin$install$2.invoke(Unknown Source:13)
at io.ktor.client.plugins.contentnegotiation.ContentNegotiation$Plugin$install$2.invoke(Unknown Source:6)
at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:123)
at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:81)
at io.ktor.client.HttpClient$4.invokeSuspend(HttpClient.kt:170)
at io.ktor.client.HttpClient$4.invoke(Unknown Source:11)
at io.ktor.client.HttpClient$4.invoke(Unknown Source:6)
at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:123)
at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:81)
at io.ktor.client.plugins.logging.Logging$setupResponseLogging$2.invokeSuspend(Logging.kt:167)
at io.ktor.client.plugins.logging.Logging$setupResponseLogging$2.invoke(Unknown Source:11)
at io.ktor.client.plugins.logging.Logging$setupResponseLogging$2.invoke(Unknown Source:6)
at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:123)
at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:81)
at io.ktor.util.pipeline.SuspendFunctionGun.proceedWith(SuspendFunctionGun.kt:91)
at io.ktor.client.plugins.HttpCallValidator$Companion$install$2.invokeSuspend(HttpCallValidator.kt:140)
at io.ktor.client.plugins.HttpCallValidator$Companion$install$2.invoke(Unknown Source:13)
at io.ktor.client.plugins.HttpCallValidator$Companion$install$2.invoke(Unknown Source:6)
at io.ktor.util.pipeline.SuspendFunctionGun.loop(SuspendFunctionGun.kt:123)
at io.ktor.util.pipeline.SuspendFunctionGun.proceed(SuspendFunctionGun.kt:81)
at io.ktor.util.pipeline.SuspendFunctionGun.execute$ktor_utils(SuspendFunctionGun.kt:101)
at io.ktor.util.pipeline.Pipeline.execute(Pipeline.kt:77)
at io.ktor.client.call.HttpClientCall.body(HttpClientCall.kt:87)
at com.example.kotlinmultiplatformsharedmodule.KtorCountryApi.getCart(KtorCountryApi.kt:53)
at com.example.kotlinmultiplatformsharedmodule.KtorCountryApi$getCart$1.invokeSuspend(Unknown Source:14)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7839)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
I am not understand what this error mean. Can someone explain me why do we need extra code for this error to solve.
You are basically trying to deserialize a response to one of two types - Success or Error but give provide your code no explicit means to discriminate between the two classes in regards to which type to use based on input fields.
For a correct solution, please follow the information found here and
use either #SerialName on each of your polymorphic sub-types in order to help the server-side properly decode them.
So, my roommate and I are trying to develop an app to help students living on campus at our school keep track of their laundry. However, we are having trouble creating new laundry loads.
Our addLoad function is supposed to add a LaundryHolder object to Firebase (containing the machine number, whether it is a washer or dryer, who owns the load, and how many seconds are left for the load), whereas the LaundryLoad object contains a LaundryHolder, observer function (notifyDataSetChanged() for the LaundryLoadFragment), and timer (with time form LaundryHolder).
In Firebase, each clothingItem has a load ID with which to identify which load it is in on the user side. For our implementation to work, we need to fetch the ID which Firebase gives our LaundryHolder, which is why we are adding an onSuccessListener to a temporary query. The issue arises, however, when the query doesn't succeed or fail, and we can't figure out what is going on here.
This is the error we get:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: edu.rosehulman.roselaundrytracker, PID: 11847
kotlin.UninitializedPropertyAccessException: lateinit property load has not been initialized
at edu.rosehulman.roselaundrytracker.model.LaundryLoadViewModel.addLoad(LaundryLoadViewModel.kt:42)
at edu.rosehulman.roselaundrytracker.adapter.AddLoadAdapter.addLoad(AddLoadAdapter.kt:67)
at edu.rosehulman.roselaundrytracker.fragment.AddLoadFragment.onCreateView$lambda-1(AddLoadFragment.kt:32)
at edu.rosehulman.roselaundrytracker.fragment.AddLoadFragment.$r8$lambda$lIyFvxsLH_bCt-kHzadMjy2Ls_Y(Unknown Source:0)
at edu.rosehulman.roselaundrytracker.fragment.AddLoadFragment$$ExternalSyntheticLambda0.onClick(Unknown Source:2)
at android.view.View.performClick(View.java:7455)
at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1119)
at android.view.View.performClickInternal(View.java:7432)
at android.view.View.access$3700(View.java:835)
at android.view.View$PerformClick.run(View.java:28810)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7842)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
Does anyone have any idea?
class LaundryLoadViewModel: ViewModel() {
private var loads = ArrayList<LaundryLoad>()
private var curPos = 0
lateinit var ref: CollectionReference
lateinit var uid: String
private var onlyOwned = true
private val subscriptions = HashMap<String, ListenerRegistration>()
fun getPreference() = onlyOwned
fun addLoad(machineNumber: Int, machineType: String, contents: ArrayList<ClothingItem>, time: Long, observer: () -> Unit){
val holder = LaundryHolder(machineNumber, machineType.lowercase(Locale.getDefault()) == "dryer", time * LaundryLoadFragment.SEC_TO_MIN, uid)
// val load = LaundryLoad(holder, observer)
// loads.add(load)
ref.add(holder)
lateinit var load: LaundryLoad
val query = ref
.whereEqualTo("machineNumber",machineNumber)
.whereEqualTo("owner",uid)
query.get().addOnSuccessListener { snapshot ->
snapshot.documents.forEach {
Log.d(Constants.TAG,"Retrieving load from Firebase")
load = LaundryLoad.from(it, observer)
}
}
query.get().addOnFailureListener {
Log.d(Constants.TAG,"Retrieval failed due to $it")
}
// val query = ref.whereEqualTo("machineNumber",machineNumber).whereEqualTo("dryer",machineType.lowercase(Locale.getDefault())=="dryer")
load.addMany(contents)
loads.add(load)
}
fun addListener(fragmentName: String, observer: () -> Unit) {
lateinit var subscription: ListenerRegistration
loads.clear()
val auth = Firebase.auth
val user = auth.currentUser!!
val clothes = ArrayList<ClothingItem>()
uid = user.uid
ref = Firebase.firestore.collection(LaundryLoad.COLLECTION_PATH)
val ref2 = Firebase.firestore.collection(ClothingItem.COLLECTION_PATH)
val inLoadQuery = ref2.whereNotEqualTo("load","")
inLoadQuery.addSnapshotListener { snapshot: QuerySnapshot?, error: FirebaseFirestoreException? ->
error?.let {
Log.d(Constants.TAG, "Error: $it")
return#addSnapshotListener
}
snapshot?.documents?.forEach {
clothes.add(ClothingItem.from(it))
}
}
if(onlyOwned) {
val query = ref.whereEqualTo("owner",uid)
subscription = query
.addSnapshotListener { snapshot: QuerySnapshot?, error: FirebaseFirestoreException? ->
error?.let {
Log.d(Constants.TAG, "Error: $it")
return#addSnapshotListener
}
retrieveLoads(snapshot, clothes, observer)
}
} else {
subscription = ref
.addSnapshotListener { snapshot: QuerySnapshot?, error: FirebaseFirestoreException? ->
error?.let {
Log.d(Constants.TAG, "Error: $it")
return#addSnapshotListener
}
retrieveLoads(snapshot, clothes, observer)
}
}
subscriptions[fragmentName] = subscription
observer()
}
private fun retrieveLoads(snapshot: QuerySnapshot?, clothes: ArrayList<ClothingItem>, observer: () -> Unit) {
snapshot?.documents?.forEach {
loads.add(LaundryLoad.from(it, observer))
}
for (load in loads) {
for (item in clothes) {
if (item.load == load.getId()) {
load.addToLoad(item)
}
}
}
}
fun removeListener(fragmentName: String) {
for(load in loads) {
ref.document(load.getId()).set(load.laundryHolder)
}
subscriptions[fragmentName]?.remove()
subscriptions.remove(fragmentName)
}
fun togglePreference() {
onlyOwned = !onlyOwned
}
}
It looks like ref has not been initialized when you ref.add(holder) in addLoad. It's impossible for us to say why that is, as the code that calls addLoad seems to be missing, but the stack trace should point you pretty directly to where the problem is.
Kotlin noob here.
I just want to ask what does this error mean?
2021-08-03 00:29:56.272 15335-15335/com.sakura.sakurafreemarket E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.sakura.sakurafreemarket, PID: 15335
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.sakura.sakurafreemarket/com.esafirm.imagepicker.features.ImagePickerActivity}: java.lang.ClassCastException: o3.a cannot be cast to q3.a
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2778)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Caused by: java.lang.ClassCastException: o3.a cannot be cast to q3.a
at com.esafirm.imagepicker.features.ImagePickerActivity.onCreate(Unknown Source:61)
at android.app.Activity.performCreate(Activity.java:7009)
at android.app.Activity.performCreate(Activity.java:7000)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2731)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
this is the layout code for the button
<com.google.android.material.button.MaterialButton
android:id="#+id/btnPostAdPhoto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/margin_medium"
android:layout_marginBottom="#dimen/margin_betweem_small_and_medium"
app:cornerRadius="#dimen/margin_large"
android:fontFamily="#font/poppins_regular"
android:includeFontPadding="false"
android:maxHeight="#dimen/margin_large_2"
android:minHeight="#dimen/margin_large_2"
android:onClick="#{() -> vm.onSelectPhotos()}"
android:text="Upload Photo"
android:textColor="#color/colorWhite"
android:textStyle="bold"
android:textSize="#dimen/font_size_extra_small"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/layoutPostAd"/>
and this is the ViewModel.kt file
var user: User? = null
var radioChecked = MutableLiveData<Int>()
var selectedPhotos = MutableLiveData<Boolean>()
var shippingInfo = MutableLiveData<Int>()
var photoId = MutableLiveData<String>()
val photoUriList = mutableListOf<File>()
val photoUpdateUriList = mutableListOf<SelectedPhotoApiResponse>()
val selectedItemResult = MutableLiveData<Resource<GetOneProductResponse>>()
val removePhotoResult = MutableLiveData<Resource<RemovePhotoResponse>>()
var sendPhotoResult = MutableLiveData<Resource<SendItemPhotosResponse>>()
var updateSendPhotoResult = MutableLiveData<Resource<SendItemPhotosResponse>>()
var sendProductResult = MutableLiveData<Resource<SendProductInfoResponse>>()
var updateOrPostStatus = MutableLiveData<Int>()
var productId = MutableLiveData<Int>()
private var imagePathListArray: ArrayList<MultipartBody.Part>? = null
var postForm = MutableLiveData<PostForm>()
private val autoCompletePublishSubjectCategory = PublishSubject.create<String>()
private val autoCompletePublishSubjectTitle = PublishSubject.create<String>()
private val autoCompletePublishSubjectPrice = PublishSubject.create<String>()
private val autoCompletePublishSubjectDescription = PublishSubject.create<String>()
private val autoCompletePublishSubjectCondition = PublishSubject.create<String>()
private val autoCompletePublishSubjectWeight = PublishSubject.create<String>()
private val autoCompletePublishSubjectLength = PublishSubject.create<String>()
private val autoCompletePublishSubjectWidth = PublishSubject.create<String>()
private val autoCompletePublishSubjectHeight = PublishSubject.create<String>()
private val autoCompletePublishSubjectCourier = PublishSubject.create<String>()
private val autoCompletePublishSubjectShippingYes = PublishSubject.create<Boolean>()
init {
user = Hawk.get<User>(Constants.PREF_KEY_USER_INFO)?.apply {}
configureInterceptorWithEmpty(autoCompletePublishSubjectCategory, 300)
.subscribe { result -> filteredCategory(result) }
configureInterceptorWithEmpty(autoCompletePublishSubjectTitle, 0)
.subscribe { result -> filteredTitle(result) }
configureInterceptorWithEmpty(autoCompletePublishSubjectPrice, 0)
.subscribe { result -> filteredPrice(result) }
configureInterceptorWithEmpty(autoCompletePublishSubjectDescription, 0)
.subscribe { result -> filteredDescription(result) }
configureInterceptorWithEmpty(autoCompletePublishSubjectCondition, 0)
.subscribe { result -> filteredCondition(result) }
configureInterceptorWithEmpty(autoCompletePublishSubjectWeight, 0)
.subscribe { result -> filteredWeight(result) }
configureInterceptorWithEmpty(autoCompletePublishSubjectLength, 0)
.subscribe { result -> filteredLength(result) }
configureInterceptorWithEmpty(autoCompletePublishSubjectWidth, 0)
.subscribe { result -> filteredWidth(result) }
configureInterceptorWithEmpty(autoCompletePublishSubjectHeight, 0)
.subscribe { result -> filteredHeight(result) }
configureInterceptorWithEmpty(autoCompletePublishSubjectCourier, 0)
.subscribe { result -> filteredCourier(result) }
initIncludeShipping()
selectedPhotos.value = false
postForm.value = PostForm()
}
fun onSelectPhotos() {
selectedPhotos.value = true
}
companion object {
const val MULTIPART_MEDIA_TYPE = "multipart/form-data"
}
and here is another code from the Activity.kt file
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (ImagePicker.shouldHandle(requestCode, resultCode, data)) {
val images = ImagePicker.getImages(data)
if (selectedProduct != null) {
var count = 0
images.forEach { image ->
val file = File(image.path)
vm.photoUpdateUriList.add(SelectedPhotoApiResponse(path = image.path, id = 0, fileImage = file))
AppLogger.error("$vm.photoUpdateUriList")
// updateImagesAdapter.collection = vm.photoUpdateUriList
photoUpdateListVisibility()
count++
AppLogger.error("${images.lastIndex} -- $count -- ${images.size}")
if (count == images.size) {
vm.updateSendPhotos()
count = 0
}
}
} else {
images.forEach { image ->
val file = File(image.path)
vm.photoUriList.add(file)
imagesAdapter.collection = vm.photoUriList
photoListVisibility()
}
vm.setPhotoFile(vm.photoUriList)
}
}
}
I have this button that opens the imagepicker. upon clicking this button, the app crashes and that error appears on logcat. I'm not really sure how to fix it since I am still studying kotlin. The code is not my original work so I'm kinda stuck on this issue for more than 2 days now.
i am not sure what the o3.a cannot be cast to q3.a mean on the stacktrace. Can someone help me understand it so I may be able to fix this issue.
Thanks
I have the following code
database.child("users").child(this.invitedBy).runTransaction(object : Transaction.Handler {
override fun doTransaction(mutableData: MutableData): Transaction.Result {
val u = mutableData.getValue(User::class.java)
?: return Transaction.success(mutableData)
if (u.numReferrals == null || u.referralEarning == null) {
// Unstar the post and remove self from stars
u.numReferrals = 1
u.referralEarning = 1;
} else {
// Star the post and add self to stars
u.numReferrals = u.numReferrals!! + 1
u.referralEarning = u.referralEarning!! + 1;
}
// Set value and report transaction success
mutableData.value = u
return Transaction.success(mutableData)
}
override fun onComplete(
databaseError: DatabaseError?,
committed: Boolean,
currentData: DataSnapshot?
) {
// Transaction completed
Log.d("MUser", "postTransaction:onComplete:" + databaseError!!)
}
})
When I run it, it gives me the following error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.test.test, PID: 5375
kotlin.KotlinNullPointerException
at com.test.test.MUser$setReferral$1.onComplete(MUser.kt:229)
at com.google.firebase.database.core.Repo$16$1.run(com.google.firebase:firebase-database##19.2.1:1006)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7478)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)
W/System.err: kotlin.KotlinNullPointerException
W/System.err: at com.test.test.MUser$setReferral$1.onComplete(MUser.kt:229)
at com.google.firebase.database.core.Repo$16$1.run(com.google.firebase:firebase-database##19.2.1:1006)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7478)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:941)
Here's my User.kt
import com.google.firebase.database.IgnoreExtraProperties
// [START rtdb_user_class]
#IgnoreExtraProperties
data class User(
var id: String = "",
var name: String = "",
var email: String = "",
var userReads: Int? = 0,
var userPlays: Int? = 0,
var userWatches: Int? = 0,
var paidDate : Int? = 0,
var endPaidDate : Int? = 0,
var paidStatus : String? = "",
var paymentMethod : String? = "",
var planid : String? = "",
var firebaseUid : String? = "",
var referralEarning : Int? = 0,
var numReferrals : Int? = 0
)
What am I doing wrong?
Please take a look at onComplete method:
override fun onComplete(
databaseError: DatabaseError?,
committed: Boolean,
currentData: DataSnapshot?
) {
// Transaction completed
Log.d("MUser", "postTransaction:onComplete:" + databaseError!!)
}
You are using !! operator when referencing databaseError parameter, but it can be null, so you can't use !!. To avoid that Exception just remove !! operator:
Log.d("MUser", "postTransaction:onComplete:" + databaseError)
databaseError: DatabaseError? - it is a nullable object (nullable objects marked with ? operator), you can't use !! operator on it if you are not 100% sure that it is not null.
Also you can use ? operator on nullable objects to call its methods or properties, e.g.:
Log.d("MUser", "postTransaction:onComplete:" + databaseError?.getMessage())
More info about Null Safety in Kotlin.