app,app/internal: [Android] replace Window.Do with ViewEvent

An event reporting the most recent Android View attached to the Window is both
simpler to implement and automatically tracks the Activity lifecycle.

The downside is that buggy programs may hold on to a stale references.
Fortunately, JNI references are handles not pointers so the always-on Android
JNI checks will very likely catch stale references on use.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2020-08-13 14:41:37 +02:00
parent c3574cdabd
commit 6c30c6386c
2 changed files with 16 additions and 64 deletions
+2 -39
View File
@@ -6,6 +6,8 @@ import (
"gioui.org/app/internal/window"
)
type ViewEvent = window.ViewEvent
// JavaVM returns the global JNI JavaVM.
func JavaVM() uintptr {
return window.JavaVM()
@@ -16,42 +18,3 @@ func JavaVM() uintptr {
func AppContext() uintptr {
return window.AppContext()
}
// Do invokes the function with a JNI jobject handle to the underlying
// Android View. The function is invoked on the main thread, and the
// handle is invalidated after the function returns.
//
// Note: Do may deadlock if called from the same goroutine that receives from
// Events.
func (w *Window) Do(f func(view uintptr)) {
type androidDriver interface {
Do(f func(view uintptr)) bool
}
success := make(chan bool)
for {
driver := make(chan androidDriver)
// two-stage process: first wait for a valid driver...
go func() {
alive := w.driverDo(func() {
driver <- w.driver.(androidDriver)
})
if !alive {
driver <- nil
}
}()
d := <-driver
if d == nil {
// Window is dead.
break
}
// .. then run the function on the main thread using the
// driver. The driver Do method returns false if the
// view was invalidated while switching to the main thread.
window.RunOnMain(func() {
success <- d.Do(f)
})
if <-success {
break
}
}
}