App crashes on nexus 6 api 24
gitAzim opened this issue · 3 comments
App is working fine mi A2 phone but facing crash on nexus 6 having api 24
GifDrawable.java – line 288
Fatal Exception: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:8358)
at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:1364)
at android.view.ViewGroup.invalidateChild(ViewGroup.java:5433)
at android.view.View.invalidateInternal(View.java:13997)
at android.view.View.invalidate(View.java:13961)
at android.view.View.invalidate(View.java:13945)
at android.widget.ImageView.invalidateDrawable(ImageView.java:262)
at android.graphics.drawable.Drawable.invalidateSelf(Drawable.java:844)
at pl.droidsonroids.gif.GifDrawable.invalidateSelf(GifDrawable.java:288)
at pl.droidsonroids.gif.InvalidationHandler.handleMessage(InvalidationHandler.java:29)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7406)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Dependency: implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.19'
Please attach a code reproducing this issue.
private var dialog: CustomProgressBar? = null
class CustomProgressBar(val activity: Activity?) {
var dialog: Dialog? =
null //..we need the context else we can not create the dialog so get context in constructor
fun showDialog() {
//start a new thread to process job
Thread(Runnable {
//heavy job here
//send message to main thread
Looper.prepare()
val v = activity?.layoutInflater?.inflate(R.layout.custom_progress_dialog, null)
dialog = activity?.let { Dialog(it, R.style.DialogStyle) }
//...that's the layout i told you will inflate later
dialog?.requestWindowFeature(Window.FEATURE_NO_TITLE)
if (v != null) {
dialog?.setContentView(v)
}
dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
//...set cancelable false so that it's never get hidden
dialog?.setCancelable(false)
dialog?.setCanceledOnTouchOutside(false)
//...initialize the imageView form infalted layout
dialog?.show()
Looper.loop()
}).start()
}
//..also create a method which will hide the dialog when some work is done
fun hideDialog() {
activity?.runOnUiThread {
dialog?.dismiss()
}
}
}
private fun getIntroImages() {
if (NetworkUtil.getConnectivityStatus(this) != 0) {
dialog?.showDialog()
disposable = Global.apiService.getLandingImages(
WebServices.LandingPageWs + Global.getLanguage(this) + "&category_id=" + Global.getPreferenceCategory(
this@SplashActivity
)
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ result ->
dialog?.hideDialog()
//hideProgressDialog()
if (result != null) {
if (result.status == 200 && result.data != null) {
val intent =
Intent(this@SplashActivity, IntroSliderActivity::class.java)
intent.putExtra("introModel", result.data)
startActivity(intent)
finish()
}
}
},
{ error ->
//println("ERROR - landing Ws : " + error.localizedMessage)
dialog?.hideDialog()
//hideProgressDialog()
init()
})
}
}
XML
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<pl.droidsonroids.gif.GifImageView
android:id="@+id/gif"
android:layout_width="@dimen/_40sdp"
android:layout_height="@dimen/_40sdp"
android:src="@drawable/loading_new"
android:visibility="visible" />
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="@dimen/_40sdp"
android:layout_height="@dimen/_40sdp"
android:visibility="gone" />
</LinearLayout>
The easiest solution coming into my mind is replacing code between Looper.prepare()
and Looper.loop()
with wrapping by Handler(Looper.getMainLooper()).post { //...
In your case:
fun showDialog() {
//start a new thread to process job
Thread(Runnable {
//heavy job here
//send message to main thread
Handler(Looper.getMainLooper()).post {
val v = activity?.layoutInflater?.inflate(R.layout.custom_progress_dialog, null)
dialog = activity?.let { Dialog(it, R.style.DialogStyle) }
//...that's the layout i told you will inflate later
dialog?.requestWindowFeature(Window.FEATURE_NO_TITLE)
if (v != null) {
dialog?.setContentView(v)
}
dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
//...set cancelable false so that it's never get hidden
dialog?.setCancelable(false)
dialog?.setCanceledOnTouchOutside(false)
//...initialize the imageView form infalted layout
dialog?.show()
}
}).start()
}