博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于android上引用js脚本 和rhino 多线程支持的问题
阅读量:6176 次
发布时间:2019-06-21

本文共 4627 字,大约阅读时间需要 15 分钟。

  好久没写过东西了,似乎只是毕业前写了一点东西,博客园开通的时间正是我去现在公司实习的时间。这一年多学了不少的东西,待我慢慢写来。

  有一阵时间我一直在研究如何在android上写js程序,当然是去掉webview这个控件 ,我想的是直接和android交互,看了网上一个被复制了很多分的文章,给我了一个提示,我找了其中一个最简单的工具 rhino javascript。刚开始用是在java程序上,调用例子和自己修改了一些地方测试都可以通过,但是放到了android上没有通过,OMG,白玩了么不是。不通过的原因是一个底层函数 ClassLoader ,java和android上机制有点差别,晕!

  后来百度的时候偶然间看到一个博友跟我想法一样并且他已经放到了android测试通过了,找到了评论 里面写的是用rhino最开始的版本是可以放到android上的。

  果断换掉最新版本的jar包,把最原始的版本jar包放到了android程序里,运行 通过了。

  好吧问题才刚刚开始,android上的js不能定义太多全局变量和函数,会产生堆栈溢出的问题。并且提示运行错误暂时还是有问题的。只能提示主js的错误。load进来的js错误是不提示的。这些用log慢慢的也可以调试,忍了!最开始学js的时候也是一个个alert调试错误,嘎嘎!好傻。

  关于堆栈溢出的问题,我想到了一个办法就是再运行时候load进来其它的js,这样就不会产生溢出了,产生了一个新的问题,直接报错了。大体是多线程不可以调用load函数,错误原因是没有Context给当前线程。因为技术原因这里必须用多线程。所以改写spawn。写了一个Thread函数。

源码如下

1     public static void Thread(Context _cx, final Scriptable thisObj, 2                             Object[] args, Function funObj) 3     { 4         for (int i=0; i < args.length; i++) { 5             final Function func=(Function) args[i]; 6             new Thread(new Runnable(){ 7  8                 @Override 9                 public void run() {10                     try {11                         func.call(cx, global, thisObj, new Object[0]);12                     } catch (JavaScriptException ex) {13                         Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);14                     }15                 }16                 17             }).start();18         }19     }

然后针对没有Context问题就要改动源码。找到Context.java 对应的函数

/**     * Get a context associated with the current thread, creating     * one if need be.     *     * The Context stores the execution state of the JavaScript     * engine, so it is required that the context be entered     * before execution may begin. Once a thread has entered     * a Context, then getCurrentContext() may be called to find     * the context that is associated with the current thread.     * 

* Calling enter() will * return either the Context currently associated with the * thread, or will create a new context and associate it * with the current thread. Each call to enter() * must have a matching call to exit(). For example, *

     *      Context cx = Context.enter();     *      ...     *      cx.evaluateString(...);     *      cx.exit();     * 
* @return a Context associated with the current thread * @see org.mozilla.javascript.Context#getCurrentContext * @see org.mozilla.javascript.Context#exit */ public static Context enter() { Thread t = Thread.currentThread(); Context cx = (Context) threadContexts.get(t); if (cx == null) { cx = new Context(); cx.currentThread = t; threadContexts.put(t, cx); } synchronized (cx) { cx.enterCount++; } return cx; } /** * Exit a block of code requiring a Context. * * Calling exit() will disassociate the Context with the * current thread if the matching call to enter() * had created a new Context. * Once the current thread no longer has an associated Context, * it cannot be used to execute JavaScript until it is again associated * with a Context. * * @see org.mozilla.javascript.Context#enter */ public synchronized void exit() { if (--enterCount == 0) { threadContexts.remove(currentThread); currentThread = null; } }

enterCount是记录当前cx线程个数的。这样很明显啊,少了一个函数啊,如何增加新的线程?没有找到对应的函数,所以添加了一个函数

public static Context enter(Context cx) {        if(cx==null)return null;        Thread t = Thread.currentThread();        threadContexts.put(t, cx);        cx.enterCount++;        return cx;    }

 重新改写Thread函数

1     public static void Thread(Context _cx, final Scriptable thisObj, 2                             Object[] args, Function funObj) 3     { 4         for (int i=0; i < args.length; i++) { 5             final Function func=(Function) args[i]; 6             new Thread(new Runnable(){ 7  8                 @Override 9                 public void run() {10                     try {11                         Context.enter(cx);12                         func.call(cx, global, thisObj, new Object[0]);13                     } catch (JavaScriptException ex) {14                         Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);15                     }16                 }17                 18             }).start();19         }20     }

好吧load函数在新线程里面没有问题了。

后续我将把android js 游戏源码发布上来共大家品评。基本上游戏的大部分功能都已经完成,待优化。

 

 

ps:cx 和 global是全局函数。具体代码请参见rhino的源码

 

 

  

  

  

 

转载于:https://www.cnblogs.com/HeiMan/p/android_javascript_rhino.html

你可能感兴趣的文章
隐藏软键盘
查看>>
用 canvas 的 getImageData 做点有趣的事
查看>>
React Native与Android通信交互
查看>>
三月面试分享
查看>>
踩坑日记-element ui树形控件
查看>>
阿里云总监课第五期PPT下载地址
查看>>
时间属性
查看>>
汽车OS混战时刻:斑马加快争夺新的应用场景
查看>>
第十九章:集合视图(十七)
查看>>
BIOS
查看>>
Elasticsearch之元数据(meta-fields)介绍
查看>>
基于Django+Bootstrap框架,可视化展示内存监控信息
查看>>
Pytorch | BERT模型实现,提供转换脚本【横扫NLP】
查看>>
biostar handbook: 第七周笔记汇总+调整通知
查看>>
涨薪必备|给你一份超详细Spring Boot知识清单
查看>>
YII2 关联查询,不修改search, 使用 GridView::widget 输出
查看>>
DNS服务-了解篇
查看>>
springcloud应用程序上下文层次结构
查看>>
Apache Shiro在web开发安全技术中的应用
查看>>
继续内存优化——一脸懵逼
查看>>