Home > other >  How to edit (Image)Views asynchronously?
How to edit (Image)Views asynchronously?

Time:03-02

I'm trying to animate an ImageView with a list of pictures, iterating through them quickly, so that it creates the impression of an animation. Sadly it does give the alert: Skipped 391 frames! The application may be doing too much work on its main thread.

This is my Main-Activity which implements the Animator-interface.

override fun onCreate(savedInstanceState: Bundle?) {
       
            GlobalScope.launch {
                show(Action.Idle)
            }
    }

My Animator show() function (runs the Runnables with android.os.Handler):

fun show(action: Action){
                getHandler().removeCallbacksAndMessages(null)
                when (action) {
                    Action.MoveRight -> getHandler().post(getRight())
                    Action.MoveUp -> getHandler().post(getUp())
                    Action.MoveDown -> getHandler().post(getDown())
                    Action.MoveLeft -> getHandler().post(getLeft())
                    Action.Idle -> getHandler().post(idle())
                }
    }

My idle function (anim.idle is an array of Ints/Drawables):

fun idle() = object : Runnable{
        override fun run() {
                val anim = getAnimation()
                repeat(anim.idle!!.size){
                    getActivity().runOnUiThread {
                        binding.figure.setImageResource(anim.idle[it])
                        binding.figure.invalidate()
                    }
                        Thread.sleep(500)
            }
            getHandler().postDelayed(this,5000)
        }
    }

CodePudding user response:

You can use AnimationDrawable to have the ImageView show a sequence of pictures, see also the guide to enter image description here

to create the animation-list in res/drawable/colored_androids.xml:

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false">
    <item android:drawable="@drawable/ic_android_blue_24dp" android:duration="250"/>
    <item android:drawable="@drawable/ic_android_mint_24dp" android:duration="250"/>
    <item android:drawable="@drawable/ic_android_green_24dp" android:duration="250"/>
    <item android:drawable="@drawable/ic_android_mint_24dp" android:duration="250"/>
</animation-list>

My Activity has a field for the AnimationDrawable

private lateinit var coloredAndroidsAnimation: AnimationDrawable

and in onCreate() the following lines are required for the setup:

findViewById<ImageView>(R.id.iv_animated).apply {
    setBackgroundResource(R.drawable.colored_androids)
    coloredAndroidsAnimation = background as AnimationDrawable

    setOnClickListener{
        coloredAndroidsAnimation.start()
    }
}

CodePudding user response:

While I don't think you can change a view that is attached to the UI from a background thread, you can create/edit views on a background thread (I do this lots)

So a possible solution might be to programmatically create a series of ImageViews in the background. It might then be possible to measure them with the same parameters as the UI in the background thread as measurement can be costly (not sure if they would be re-measured when added to the UI)

Then in the UI thread your loop would add and remove Views from the parent view.

CodePudding user response:

I finally solved this problem. The Handler and the Callback seemed to cause this issue. I changed it into a while and now everything is working just fine.

  • Related