代码之家  ›  专栏  ›  技术社区  ›  Rajath

在Android预版Kitkat中模拟Web Workers

  •  1
  • Rajath  · 技术社区  · 11 年前

    由于Webworkers仅从Android 4.4开始实现,那么在应用程序代码中是否可以有一个包装器来为包含的WebView提供此功能?

    一个关于如何解决这个问题的例子将非常有用。

    谢谢
    拉贾斯

    2 回复  |  直到 11 年前
        1
  •  1
  •   aravind    11 年前

    我猜你说的是在后台运行javascript代码块,即不同的线程。曾在Android上使用RhinoJS尝试过这样做。在Android 2.2及以上版本上测试

    https://github.com/devthon/SilentJSAndroid

    主要特点是

    1. 在没有浏览器上下文的情况下执行Javascript代码
    2. 从脚本文件执行Javascript代码
    3. 在同一上下文中加载其他JS文件
    4. 在后台线程中执行方法并返回结果
    5. 执行Object.Method()调用
    6. 执行原型方法调用
    7. 关闭应用程序后,在后台运行长运行脚本。

    可能不是一个成熟的Web工作者,因为它没有API来检查两者之间的状态。但我相信这仍然可以添加到界面中。

    如果这是你正在寻找的方向,我可以解释更多关于它是如何实现的。

        2
  •  0
  •   ksasq    11 年前

    您需要实现多少Worker规范,实现需要多灵活?您可能可以使用JavaScript接口[1]启动并运行基本功能,并从Java本地生成线程。然而,这将很快变得复杂。

    如果你能描述一下你在用什么样的工人,我也许能提供一个不同的/更好的建议。

    [1] http://developer.android.com/reference/android/webkit/WebView.html#addJavascriptInterface(java.lang.Object ,java.lang.String)

    --

    添加一些伪代码

    在JavaScript中生成Java工作线程:

    var worker_id = window.Android.spawnWorker();
    

    在JavaScript中,在该工作程序上运行一个任务:

    var task_id = window.Android.doAdditionOnWorker(2,2, worker_id);
    

    用JavaScript处理结果

    function onReceiveResultForWorkerTask(task_id, result) {
        alert("the answer was " + result);
    }
    

    Java端:

    public int spawnWorker() {
        HandlerThread worker = new HandlerThread();
        worker.start();
        Handler h = new Handler(worker.getLooper()) {
            @Override
            handleMessage(Message msg) {
               switch(msg.what) 
               case ADD:
                   // calculate the answer and send back to JS via UI thread
                   // Unpack parameters and task id from Message               
                   mWebView.post(new Runnable(
                       public void run() {
                           mWebView.loadUrl("javascript:onReceiveResultForWorkerTask(task_id, " + (a+b) +");");
                       }
                   )
            }
        };
    
        mWorkerMap.put(mWorkerId++, h);
        return mWorkerId;
    }
    
    public int doAdditionOnWorker(int a, int b, int worker_id) {
        Handler h = mWorkerMap.get(worker_id);
        Bundle b = new Bundle();
        int task_id = mTaskId++;
        // pack arguments and task_id into the bundle
        h.postMessage(Message.obtain(h, ADD, b);
        return task_id;
    }
    

    当应用程序不再需要时,不要忘记查看并删除所有生成的工作线程。根据需要多少工作人员,您也可能更喜欢使用线程池,而不是每次都创建新线程。