How to reference a method inside a button click - android

I am learning kotlin. i set button click handler in the xml as shown below in the code..when the button is clicked i call the method beginSearch(), but then the App crash and i receive the below posted
error.
please let me know how to fix this error.
Activity
private fun clickHandler(v : View?) : Unit {
when(v?.id) {
R.id.btnCheckSearchResult -> beginSearch("Trump")
}
}
button:
<Button
android:id="#+id/btnCheckSearchResult"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Check Search Result"
android:layout_below="#id/etSearchEntry"
android:onClick="clickHandler"/>
error:
--------- beginning of crash
2019-07-09 15:02:06.146 14883-14883/com.example.retrofitkotlin_v10 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.retrofitkotlin_v10, PID: 14883
java.lang.IllegalStateException: Could not find method clickHandler(View) in a parent or ancestor Context for android:onClick attribute defined on view class android.support.v7.widget.AppCompatButton with id 'btnCheckSearchResult'
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.resolveMethod(AppCompatViewInflater.java:424)
at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:381)
at android.view.View.performClick(View.java:6256)
at android.view.View$PerformClick.run(View.java:24701)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

java.lang.IllegalStateException: Could not find method
clickHandler(View) in a parent or ancestor Context for android:onClick
attribute defined on view class
android.support.v7.widget.AppCompatButton with id
'btnCheckSearchResult'
Remove android:onClick="clickHandler" from XML
And try with
btnCheckSearchResult.setOnClickListener {
beginSearch("Trump")
}
And
import kotlinx.android.synthetic.main.your_layout.*

Function must be public (or protected).
public fun clickHandler(v : View?) : Unit {
when(v?.id) {
R.id.btnCheckSearchResult -> beginSearch("Trump")
}
}
P.S - You could also use setOnClickListener as the other answers have pointed out.

Just use
btnCheckSearchResult.setOnClickListener {
beginSearch("Trump")
}
or
btnCheckSearchResult.setOnClickListener({
beginSearch("Trump")
})

make your function public
public fun clickHandler(v : View?) : Unit {
when(v?.id) {
R.id.btnCheckSearchResult -> beginSearch("Trump")
}
}

Related

Why dialog fragment dissmiss and lose data onconfiguration change

I have dialog fragment containes list of users so When my dialog fragment is showing and I change let's say the language or activate or disactivate dark mode or any other config change my dialog fragment dissmiss and lose state
so this how i create the dialog :
CheckableContactsDialog.newInstance(object : CheckableContactListener {
override fun onPositiveClick(selected: MutableList<String>) {
checkableContactsDialog?.dismiss()
if (mVCall != null) {
val (phones, phoneFlat) = extractPhonesNumberFromContacts(
context, selected
)
if (phones.isEmpty()) {
return
}
inviteNewUsers(phoneFlat)
}
}
override fun onNegativeClick() {
checkableContactsDialog?.dismiss()
}
})
After configchange like language change or activate or desactivate dark mode and trigger the onPositiveClick event and checkableContactsDialog?.dismiss() called this error appear
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.zetabox.totrapp, PID: 4368
java.lang.IllegalStateException: Fragment CheckableContactsDialog{58e7d9c} (77fb6c1e-6986-4eb0-8e35-c1ee51f4e0c9) not associated with a fragment manager.
at androidx.fragment.app.Fragment.getParentFragmentManager(Fragment.java:1040)
at androidx.fragment.app.DialogFragment.dismissInternal(DialogFragment.java:350)
at androidx.fragment.app.DialogFragment.dismiss(DialogFragment.java:307)
at com.google.android.material.bottomsheet.BottomSheetDialogFragment.dismiss(BottomSheetDialogFragment.java:47)
at com.zetabox.totrapp.ui.call.CallActivity$showAddUserDialog$1.onPositiveClick(CallActivity.kt:2123)
at com.zetabox.totrapp.ui.dialogs.CheckableContactsDialog.init$lambda-7(CheckableContactsDialog.kt:231)
at com.zetabox.totrapp.ui.dialogs.CheckableContactsDialog.$r8$lambda$BXYvl1NNrhMJYwo5PbYyZJ1LQtM(Unknown Source:0)
at com.zetabox.totrapp.ui.dialogs.CheckableContactsDialog$$ExternalSyntheticLambda0.onClick(Unknown Source:2)
at android.view.View.performClick(View.java:7171)
at android.view.View.performClickInternal(View.java:7148)
at android.view.View.access$3500(View.java:802)
at android.view.View$PerformClick.run(View.java:27409)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7650)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:503)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)

Dynamic Feature Crashing Resource not found on Application Relaunch

My app works fine after downloading Dynamic Feature onDemand Module but as soon as I restart my app the app crashes with Exception.
Heres the code that I copied from google dynamic features [sample repo][1]
private fun onSuccessfulLoad(moduleName: String, launch: Boolean) {
if (launch) {
when (moduleName) {
pagesfeatures -> launchActivity(mainActivity)
}
}
}
I have already overridden the code in BaseActivity and App class
open class BaseActivity: AppCompatActivity() {
override fun attachBaseContext(newBase: Context?) {
super.attachBaseContext(newBase)
SplitCompat.install(this)
}
}
public class App extends Application {
#Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
SplitCompat.install(base);
}
}
But its crashing when I revisit the application
The Exception thats occurring in my logs Crashlytics
Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.qp.readquranoffline.holybookreading/com.mycode.pagesfeature.activities.MainActivity}: android.content.res.Resources$NotFoundException: Resource ID #0x7e010000
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3621)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3866)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2190)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:268)
at android.app.ActivityThread.main(ActivityThread.java:8004)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:627)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:997)
Caused by android.content.res.Resources$NotFoundException: Resource ID #0x7e010000
at android.content.res.ResourcesImpl.getValue(ResourcesImpl.java:248)
at android.content.res.Resources.loadXmlResourceParser(Resources.java:2400)
at android.content.res.Resources.getAnimation(Resources.java:1277)
at android.view.animation.AnimationUtils.loadAnimation(AnimationUtils.java:138)
at com.mycode.quranpagesfeature.activities.MainActivity.onCreate(MainActivity.kt:158)
at android.app.Activity.performCreate(Activity.java:8058)
at android.app.Activity.performCreate(Activity.java:8042)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1315)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3594)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3866)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2190)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:268)
at android.app.ActivityThread.main(ActivityThread.java:8004)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:627)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:997)
[1]: https://github.com/googlearchive/android-dynamic-features
In my case, when there’s a configuration change it also regenerates the Context in my Activity, and loses the resources that have been injected by SplitCompat. I fix it by loading the resources using ContextCompat.
ContextCompat.getDrawable(context, drawable)
And reinject resource when there`s configuration changes using this in activity
override fun onConfigurationChanged(newConfig: Configuration) {
SplitCompat.installActivity( baseContext ?: this)
super.onConfigurationChanged(newConfig)
}

Android Studio kotlin app "keep stopping" error

package com.example.absolutelydumb
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.InputType
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import kotlinx.android.synthetic.main.activity_main.*
//sets var to some random number and asks for a guess, giving feedback on proximity to answer
class MainActivity : AppCompatActivity() {
private val startButton: Button = findViewById(R.id.startButton)
private val submitButton: Button = findViewById(R.id.submit)
private val instructionsText: TextView = findViewById(R.id.instructionView)
private val response: EditText = findViewById(R.id.answerInput)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val startText: String = getString(R.string.startText)
startButton.text = startText
//TODO("Add autofillHints")
startButton.setOnClickListener {
numberGuess()
}
//TODO("Set text back to start after guessing is done")
}
fun numberGuess() {
response.inputType = InputType.TYPE_CLASS_NUMBER
val clickText: String = getString(R.string.clickText)
startButton.text = clickText
//TODO("Add autofillHints")
instructionsText.text = getString(R.string.instructions)
val randomNumber: Int = rand(0,10)
submitButton.setOnClickListener {
val responseText = Integer.parseInt(answerInput.text.toString())
if(responseText == randomNumber) {
instructionsText.text = getString(R.string.correctGuess)
} else {
instructionsText.text = getString(R.string.badGuess)
}
}
}
fun rand(start: Int, end: Int): Int {
//require(start <= end) { "Illegal Argument" }
return (start..end).random()
}
}
Above is the code that I've been writing. This is my first project, so I don't know what went wrong. I fixed a variable type problem in the numberGuess function but when I finished fixing it the app wouldn't open and the virtual device stated a "app keeps stopping" error.
Here is the Run log that lists off errors. The build log didn't have any errors.
07/09 19:58:05: Launching 'app' on phone1.
Install successfully finished in 1 s 266 ms.
$ adb shell am start -n "com.example.absolutelydumb/com.example.absolutelydumb.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Connected to process 5935 on device 'phone1 [emulator-5554]'.
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.absolutelydumb, PID: 5935
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.absolutelydumb/com.example.absolutelydumb.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2843)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference
at android.content.ContextWrapper.getApplicationInfo(ContextWrapper.java:159)
at android.view.ContextThemeWrapper.getTheme(ContextThemeWrapper.java:157)
at android.content.Context.obtainStyledAttributes(Context.java:675)
at androidx.appcompat.app.AppCompatDelegateImpl.createSubDecor(AppCompatDelegateImpl.java:692)
at androidx.appcompat.app.AppCompatDelegateImpl.ensureSubDecor(AppCompatDelegateImpl.java:659)
at androidx.appcompat.app.AppCompatDelegateImpl.findViewById(AppCompatDelegateImpl.java:479)
at androidx.appcompat.app.AppCompatActivity.findViewById(AppCompatActivity.java:214)
at com.example.absolutelydumb.MainActivity.<init>(MainActivity.kt:13)
at java.lang.Class.newInstance(Native Method)
at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:69)
at androidx.core.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:45)
at android.app.Instrumentation.newActivity(Instrumentation.java:1215)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2831)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048) 
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78) 
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808) 
at android.os.Handler.dispatchMessage(Handler.java:106) 
at android.os.Looper.loop(Looper.java:193) 
at android.app.ActivityThread.main(ActivityThread.java:6669) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 
You cannot call findViewById before onCreate() or setContentView() is called. Since you are using findViewById at the declaration site of your four properties, it is being called at the time your Activity class is being instantiated, which is before onCreate is called.
There are two ways to handle this.
Use lateinit var and set the properties right after your call to setContentView():
private lateinit var startButton: Button
//...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button = findViewById(R.id.startButton)
//...
Use by lazy so it is only called when the property is first accessed, which will be after setContentView() is called:
private val startButton: Button by lazy { findViewById(R.id.startButton) }
Or you can use view binding, which gets rid of most of this boilerplate and is less error-prone. By error-prone, I mean you can call findViewById and accidentally search for a view that isn't present in the current layout and it will crash at runtime. View binding makes this impossible.

Inlining codes with coroutines to inside of button.setOnClickListener makes app crash

This is the summary of some codes which I am trying to implement.
button.setOnClickListener {
showSomeAnimation()
CoroutineScope(Dispatchers.IO).launch { // this line is UserActivity.kt:138
someNetworkTasks()
withContext(Dispatchers.Main) {
updateUI()
}
}
}
However, once I press the button, java.lang.VerifyError occurs:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.diy.drift, PID: 25461
java.lang.VerifyError: Verifier rejected class com.diy.drift.UserActivity$onCreate$$inlined$forEachIndexed$lambda$1$1: java.lang.Object com.diy.drift.UserActivity$onCreate$$inlined$forEachIndexed$lambda$1$1.invokeSuspend(java.lang.Object) failed to verify: java.lang.Object com.diy.drift.UserActivity$onCreate$$inlined$forEachIndexed$lambda$1$1.invokeSuspend(java.lang.Object): [0xDB] 'this' argument 'Uninitialized Reference: com.diy.drift.UserActivity$onCreate$$inlined$forEachIndexed$lambda$1$1$4 Allocation PC: 217' not instance of 'Precise Reference: com.diy.drift.UserActivity$onCreate$$inlined$forEachIndexed$lambda$1$1$3' (declaration of 'com.diy.drift.UserActivity$onCreate$$inlined$forEachIndexed$lambda$1$1' appears in /data/app/com.diy.drift-fU12pqcCpebCBPw2Tcgk-w==/base.apk!classes2.dex)
at com.diy.drift.UserActivity$onCreate$$inlined$forEachIndexed$lambda$1.onClick(UserActivity.kt:138)
at android.view.View.performClick(View.java:6612)
at android.view.View.performClickInternal(View.java:6581)
at android.view.View.access$3100(View.java:785)
at android.view.View$PerformClick.run(View.java:25904)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:280)
at android.app.ActivityThread.main(ActivityThread.java:6706)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
I thought that there can be some errors on my code and exception weren't printed definitely because the code is inside of lambda. So I extracted all of codes which are in button.setOnClickListener to a function to see what is the problem of my code like this:
fun foo() {
showSomeAnimation()
CoroutineScope(Dispatchers.IO).launch {
someNetworkTasks()
withContext(Dispatchers.Main) {
updateUI()
}
}
}
button.setOnClickListener {
foo()
}
But it worked really well without any exception. Why did this strange thing happen to me?
Try using
GlobalScope.launch {
someNetworkTasks()
}
updateUI()
Hope this helps

Protected method not accessible from subclass

I know this has been asked before but my problem is strange and I couldn't find an answer.
I have a parent class where a member is declared protected
class BaseContoller<G: BaseContract.BasePresenter, F: BaseModel> {
protected var presenter: G? = null
// ...
}
In each of BaseController's descendants, I refer to presenter with no problem as it is accessible in the same package and subclasses.
One BaseController's descendant has to be extended by other classes too but I have to do one check before of performing certain actions in where presenter is referenced again
class BackupPrinterController<G: BackupPrinterContract.Presenter, F: BaseModel>: BackupController<G, F>
private fun startScan() {
if(this is PrinterAssociationController) {
PrinterConnection.onConnection = { presenter?.onDeviceConnected(it) }
// ...
}
}
}
The strange behaviour comes here, presenter is perfectly accessible only without the filter if(this is PrinterAssociationController), with that if statement, when the onConnection callback is invoked, an IllegalAccessError exception is thrown by presenter
Here is the declaration of PrinterAssociationController
class PrinterAssociationController: BackupPrinterController<PrinterAssociationContract.Presenter, PrinterAssociationModel>(),
PrinterAssociationContract.View
and here is the exception
java.lang.IllegalAccessError: Method 'package.common.base.BaseContract$BasePresenter package.common.base.BaseController.getPresenter()' is inaccessible to class 'package.project.features.shared.controllers.BackupPrinterController$startScan$1' (declaration of 'package.project.features.shared.controllers.BackupPrinterController$startScan$1' appears in /data/app/package.project-1/base.apk:classes2.dex)
at package.project.features.shared.controllers.BackupPrinterController$startScan$1.invoke(BackupPrinterController.kt:53)
at package.project.features.shared.controllers.BackupPrinterController$startScan$1.invoke(BackupPrinterController.kt:35)
at package.project.utils.print.PrinterConnection$scan$1$4.accept(PrinterConnection.kt:84)
at package.project.utils.print.PrinterConnection$scan$1$4.accept(PrinterConnection.kt:24)
at io.reactivex.internal.observers.LambdaObserver.onNext(LambdaObserver.java:63)
at io.reactivex.internal.operators.observable.ObservableFilter$FilterObserver.onNext(ObservableFilter.java:52)
at io.reactivex.internal.operators.observable.ObservableDistinct$DistinctObserver.onNext(ObservableDistinct.java:85)
at io.reactivex.internal.operators.mixed.CompletableAndThenObservable$AndThenObservableObserver.onNext(CompletableAndThenObservable.java:65)
at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.tryEmit(ObservableFlatMap.java:265)
at io.reactivex.internal.operators.observable.ObservableFlatMap$InnerObserver.onNext(ObservableFlatMap.java:562)
at io.reactivex.internal.operators.observable.ObservableDoOnEach$DoOnEachObserver.onNext(ObservableDoOnEach.java:101)
at io.reactivex.internal.operators.observable.ObservableMap$MapObserver.onNext(ObservableMap.java:62)
at io.reactivex.internal.operators.observable.ObservableUnsubscribeOn$UnsubscribeObserver.onNext(ObservableUnsubscribeOn.java:60)
at io.reactivex.internal.operators.observable.ObservableCreate$CreateEmitter.onNext(ObservableCreate.java:66)
at com.polidea.rxandroidble2.internal.serialization.FIFORunnableEntry$1.onNext(FIFORunnableEntry.java:66)
at io.reactivex.internal.operators.observable.ObservableUnsubscribeOn$UnsubscribeObserver.onNext(ObservableUnsubscribeOn.java:60)
at io.reactivex.internal.operators.observable.ObservableSubscribeOn$SubscribeOnObserver.onNext(ObservableSubscribeOn.java:58)
at io.reactivex.internal.operators.observable.ObservableCreate$CreateEmitter.onNext(ObservableCreate.java:66)
at com.polidea.rxandroidble2.internal.operations.ScanOperationApi21$1.onScanResult(ScanOperationApi21.java:77)
at android.bluetooth.le.BluetoothLeScanner$BleScanCallbackWrapper$1.run(BluetoothLeScanner.java:471)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at com.osama.firecrasher.FireLooper.run(FireLooper.kt:39)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6780)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1500)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1390)
I don't understand why this is happening when I put that if statement

Categories

Resources