【问题标题】:How to deattach webview once attached?附加后如何分离webview?
【发布时间】:2016-07-19 09:27:22
【问题描述】:

我已成功将 WebView 附加到我的 Kivy 应用 following Kivy wiki instructions。它按预期工作,但我想分离并返回到我的正常 Kivy ui。我该怎么做?

我试图探索 WebView documentation,访问它的方法(WebView.destroy() 抱怨破坏仍然连接的 WebView),它是父方法(我什至不确定这是否是要走的路),但我无法摆脱 WebView。

【问题讨论】:

  • 使用 WebView.loadUrl("about:blank") 可靠地重置视图状态并释放页面资源(包括任何正在运行的 JavaScript)。这是否允许您随后销毁 Web 视图?
  • 我对 Kivy 了解不多,但你可以看看stackoverflow.com/a/28964755/4033690
  • 实际上我已经找到了解决这个问题的方法,我不确定它是否是最好的方法,但是可以。销毁webview本身实际上并不是问题,问题在于应用程序活动被webview“拥有”(finish(),destroy()方法实际上会杀死整个应用程序,而不仅仅是webview),所以它需要android.runnable 和 kivy 的主线程的 ui 线程几乎没有杂耍。正如我所说,我不确定这是最好的方法,但这是我所知道的唯一方法。有时间我会尽快发布答案。

标签: android python webview kivy


【解决方案1】:

好的,我不确定这是否是最好的解决方案,或者是否足够干净,但我知道这是唯一可行的解​​决方案。虽然它可以工作并且看起来很稳定,但它需要由更了解 Kivy 和 Android API 本身的人进行进一步测试。

if platform == 'android':
    from jnius import autoclass
    from android.runnable import run_on_ui_thread
    WebView = autoclass('android.webkit.WebView')
    WebViewClient = autoclass('android.webkit.WebViewClient')
    activity = autoclass('org.renpy.android.PythonActivity').mActivity
else:
    import webbrowser
    def run_on_ui_thread(func):
        ''' just for desktop compatibility '''
        return func


class MyScreen(Screen):
    view_cached = None  # make these object properties?
    webview     = None
    wvc         = None  # not even needed probably
    code        = StringProperty() # this property triggers webview to close
    url_to_load = None

    def on_enter(self):
        if platform == 'android':
            Clock.schedule_once(self.create_webview, 0) # probably doesn't need clocked call (because decorators will make sure
                                                        # function runs on correct thread), but leaving it until tested properly
        else:           
            webbrowser.open_new(self.url_to_load)       # on desktop just run the webbrowser

    @run_on_ui_thread
    def on_code(self, *args):
        ''' runs when you are ready to detach WebView '''
        self.detach_webview()

    @run_on_ui_thread
    def create_webview(self, *args):
        ''' attaching webview to app '''
        if self.view_cached is None:
            self.view_cached = activity.currentFocus # caches current view (the one with kivy) as a view we want to go back to; currentFocus or getCurrentFocus() works
        self.webview = WebView(activity)
        settings = self.webview.getSettings()
        settings.setJavaScriptEnabled(True)         # enables js
        settings.setUseWideViewPort(True)           # enables viewport html meta tags
        settings.setLoadWithOverviewMode(True)      # uses viewport
        settings.setSupportZoom(True)               # enables zoom
        settings.setBuiltInZoomControls(True)       # enables zoom controls
        self.wvc = WebViewClient()
        self.webview.setWebViewClient(self.wvc)
        activity.setContentView(self.webview)
        self.webview.loadUrl(self.url_to_load)  

    @run_on_ui_thread
    def key_back_handler(self, *args):
        ''' sketch for captured "key back" event (in App), not tested properly '''
        if self.webview:
            if self.webview.canGoBack() == True:
                self.webview.goBack()
            else:
                self.detach_webview()
                Clock.schedule_once(self.quit_screen, 0)
        else:
            App.get_running_app().root.current = 'some_other_screen_to_switch_to'

    @run_on_ui_thread
    def detach_webview(self, *args):
        if self.webview:
            self.webview.clearHistory()
            self.webview.clearCache(True)
            self.webview.loadUrl("about:blank")
            self.webview.freeMemory()                   # probably not needed anymore
            self.webview.pauseTimers()                  # this should stop any playing content like videos etc. in the background; probably not needed because of 'about:blank' above
            activity.setContentView(self.view_cached)   # sets cached view as an active view
            #self.webview = None # still needs testing;
            #self.wvc = None            

    @mainthread
    def quit_screen(self, *args):
        ''' if not called on @mainthread, it will be freezed '''
        app = App.get_running_app()
        app.root.current = 'some_other_screen_to_switch_to'

我在进入 MyScreen(Screen) 时创建 WebView,当分离 WebView 时,切换回其他屏幕。

WebView 被缓存之前的视图(这效率高吗?可能以其他方式访问它会更好)并在 WebView 被销毁时再次使用。 quit_screen() 调用可能应该移至 detach_webview(),但整个代码可能需要更好的组织,所以保持原样,因为这是经过测试的示例。

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-06
  • 2013-11-10
  • 2016-06-25
相关资源
最近更新 更多