https://kotlinlang.org logo
m

myanmarking

09/01/2023, 11:26 AM
Is there any kind of mutex available that i can use in drawWithCache ?
s

svenjacobs

09/01/2023, 11:29 AM
I believe people can better help you if you show a code sample of what you want to achieve and what currently is not working for you.
m

myanmarking

09/01/2023, 11:30 AM
the problem is Dispatcher.IO, when saving is happening, a new recording can happen, which is illegal and crash
i need to somehow syncronize the two
s

svenjacobs

09/01/2023, 11:32 AM
I recently saw this post by @Rebecca Franks. Does it help maybe?
m

myanmarking

09/01/2023, 11:32 AM
yes, i am using that approach. the problem is, that approach has a problem
when you create the bitmap from the Picture, endRecording must be called. Since you cannot control when the composable calls draw. You can try to save while the render process is in the middle
s

svenjacobs

09/01/2023, 11:34 AM
Hm, maybe Rebecca has an idea?
m

myanmarking

09/01/2023, 11:34 AM
and that will crash
ok. ill try to ping her. thanks
s

svenjacobs

09/01/2023, 11:35 AM
Why do you use
<http://Dispatcher.IO|Dispatcher.IO>
?
m

myanmarking

09/01/2023, 11:35 AM
its in the google sample. it can be heavy operation
s

svenjacobs

09/01/2023, 11:36 AM
I don’t see a Dispatcher mentioned in the example here 👀
m

myanmarking

09/01/2023, 11:37 AM
it is in the original link i provided. It is compose team sample 😛
coroutineScope.launch(<http://Dispatchers.IO|Dispatchers.IO>) {
val bitmap = createBitmapFromPicture(picture)
val uri = bitmap.saveToDisk(context)
shareBitmap(context, uri)
}
createBitmap happens in another dispatcher. Which can cause this problem
s

svenjacobs

09/01/2023, 11:38 AM
Hm, yeah, we need Rebecca who is the author of this code, I guess 😅
m

myanmarking

09/01/2023, 11:38 AM
i can solve the problem keeping a Picture object per render. Which may be expensive also 😛
s

svenjacobs

09/01/2023, 11:39 AM
Have you tried the simple example from the website?
m

myanmarking

09/01/2023, 11:40 AM
Again, the google sample as it is has this bug. I did no try rebeka approach, which i believe is similar. let me check
👍🏼 1
ya, its the same
🤔 1
i solved with sth like this, no idea if it is expensive
z

Zach Klippenstein (he/him) [MOD]

09/01/2023, 1:21 PM
@Rebecca Franks
m

myanmarking

09/01/2023, 1:55 PM
I ended up doing something like this:
Copy code
private val pictureMutex = Mutex()
private val picture = Picture()

fun record(
        scope: ContentDrawScope,
        width: Int,
        height: Int
    ) {
        val locked = pictureMutex.tryLock()

        if (locked) {
            try {
                with(scope) {
                    val canvas = Canvas(picture.beginRecording(width, height))
                    draw(scope, scope.layoutDirection, canvas, scope.size) {
                        this@with.drawContent()
                    }
                    picture.endRecording()
                    drawIntoCanvas { drawCanvas ->
                        drawCanvas.nativeCanvas.drawPicture(picture)
                    }
                }
            } finally {
                pictureMutex.unlock()
            }
        } else {
            scope.drawContent()
        }
    }

    fun capture() {
        scope.launch {
            try {
                val bitmap = withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
                    pictureMutex.withLock {
                        createBitmapFromPicture(picture)
                    }
                }
            }
        }
    }
It will suspend while trying to create the bitmap until the recording is finished. If it is attempting to record while saving is happening, it will skip recording. I think it is a better solution, since it does not mess with the drawing phase. Feedback from @Rebecca Franks is needed!
s

svenjacobs

09/01/2023, 1:58 PM
@myanmarking FYI, when you use ````` (three backticks) you can properly format a block of code
👍 1
r

Rebecca Franks

09/01/2023, 2:06 PM
Thanks folks for the feedback, this doesn't sound great I agree. (cc @Nader Jawad too for context as he is also looking into improving the solution to use bitmaps with hardware acceleration across all versions of Android). Will revert back when we have an official solution here thank you color
🙏🏼 1
🙏 1
n

Nader Jawad

09/07/2023, 7:42 PM
You can probably get away with removing the coroutine usage here to avoid concurrency concerns.
m

myanmarking

09/07/2023, 7:46 PM
That why there is a mutex
The bitmap is heavy. Cannot use main thread
But ya. On the main thread no probs
n

Nader Jawad

09/07/2023, 7:48 PM
It is reasonable to render content into an offscreen bitmap as part of a typical render pass. The Android graphics pipeline does this internally for various use cases when content is promoted to a layer. While we should persist these bitmaps/layers across frames, doing a 1 off render if not prohibitive if done sparingly.
👍 1
m

myanmarking

09/07/2023, 7:49 PM
The usage of io dispatcher is in google examples, not mine. I just caught the problem here :)
n

Nader Jawad

09/07/2023, 7:50 PM
@Rebecca Franks do you think we can update these samples here 🙂
m

myanmarking

09/07/2023, 7:51 PM
I think the mutex solution is reasonable. It wont suspend when drawing. It will just do draw pass without capturing anything
Il wait for official fix. Can confirm no problems so far
r

Rebecca Franks

09/11/2023, 11:34 AM
@Nader Jawad thanks - yup will do!
108 Views