1

I have following situation in my fragment.

 @SuppressLint("ClickableViewAccessibility")
override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    val view = inflater.inflate(R.layout.streaming_fragment, container, false)
    val button = view.findViewById<Button>(R.id.radio_button)
    val pb = view.findViewById<ProgressBar>(R.id.progressBar)

    button.setOnClickListener {
        if (mediaPlayer.isPlaying) {
            this.mediaPlayer.pause();
        } else {
            pb.visibility = View.VISIBLE
            this.mediaPlayer.reset()
            this.mediaPlayer.setDataSource(
                requireContext(),
                Uri.parse("https://xxx.mp3")
            )
            this.mediaPlayer.prepare()
            this.mediaPlayer.start();
            pb.visibility = View.INVISIBLE
        }

        this.renderButtonBackground()
    }

    return view;
}

But the instruction pb.visibility = View.VISIBLE seems not working, beacause the thread of view refresh is "locked" by following instruction

                this.mediaPlayer.reset()
                this.mediaPlayer.setDataSource(
                    requireContext(),
                    Uri.parse("https://xxx.mp3")
                )
                this.mediaPlayer.prepare()
                this.mediaPlayer.start();

In fact, if I comment this line

pb.visibility = View.INVISIBLE

the spinner appear after the MediaPlayer started playing streaming audio.

How can I avoid this behavoir? Is there a way to give priority to first instruction?

Thanks... Sorry but I am new on Android.

1 Answers1

3

All the code you have shown is running on the main (UI) thread. The documentation clearly states that MediaPlayer.prepare() can take a long time and should never be called on the main (UI) thread. The documentation even explains how to do this using MediaPlayer.prepareAsync().

See https://developer.android.com/guide/topics/media/mediaplayer?hl=en#preparingasync

David Wasser
  • 93,459
  • 16
  • 209
  • 274
  • What's specifically happening in your case, is you're setting the visibility on the progress bar, but then you're doing this long-running ``prepare()`` call (which involves a network request too!) that blocks the main thread. This means that even though you've changed the visibility state of the widget, *it can't be redrawn* until the system gets around to updating the display, which is a recurring task it will get to *later*. And it can't do that while the thread is blocked - that's why it seems to happen when the ``prepare()`` call finally finishes – cactustictacs May 05 '22 at 00:23
  • 1
    Thanks! I used prepareAsync and preparedListener to achieve – Claudio Merli May 06 '22 at 20:22