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 Answer 1

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

2
  • 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 Commented May 5, 2022 at 0:23
  • 1
    Thanks! I used prepareAsync and preparedListener to achieve Commented May 6, 2022 at 20:22

Not the answer you're looking for? Browse other questions tagged or ask your own question.