【问题标题】:Android Phonegap: Notify javascript when an AsyncTask is finishedAndroid Phonegap:AsyncTask 完成时通知 javascript
【发布时间】:2011-10-13 08:43:54
【问题描述】:

在我的应用程序中,当用户单击 webview 中的按钮时,将调用 phonegap 插件来触发异步任务以从 Internet 下载文件。现在我想在异步任务完成时将信号发送回 javascript 部分。但我不知道该怎么做,因为我的插件在异步任务完成之前已经发回了一些东西。有谁知道我如何在没有 Phonegap 插件的情况下通知我的 javascript 部分?

【问题讨论】:

    标签: javascript android cordova android-asynctask


    【解决方案1】:

    我也在 Phonegap Google Group 中问过这个问题,这是 Simon Mac Donald 的回复。它非常适合我:


    您可以通过使用插件 API 非常轻松地处理这种情况。它 在核心 API 项 Connection 和 Battery 中实现。你什么 需要做的是:

    1) 在插件的 execute() 方法中保存你得到的 callbackId。

    2) 返回一个 NO_RESULT 插件结果并将保持回调 id 设置为 true。

        PluginResult pluginResult = new  PluginResult(PluginResult.Status.NO_RESULT); 
        pluginResult.setKeepCallback(true); 
        return pluginResult; 
    

    3) 当你异步java方法完成返回另一个插件结果是这样的:

        PluginResult result = new PluginResult(PluginResult.Status.OK, data); 
        result.setKeepCallback(false); 
        this.success(result, this.myCallbackId); 
    

    正如我所说,您可以查看 GitHub 中的代码,了解我们如何将其用于连接和电池。


    【讨论】:

    • ...我做了上面提到的同样的事情,但它并不总是有效,有时我看到 HTML 上的值,有时是一个空白页。请参阅此链接stackoverflow.com/questions/25780372/…
    • github repo 链接在哪里?
    【解决方案2】:

    这就是我解决像你这样的问题的方法。

    1) 创建一个 JavascriptInterface 并将其关联到您的 WebView。 JavascriptInterface 只是一个类,您可以在其中声明一些您想从 JS 中使用的 Java 方法。

    public class JSInterface() {
        private final CountDownLatch latch = new CountDownLatch(1);
    
        public void waitForProceed() {
            try {
                latch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        public void canProceed() {
            latch.countDown();
        }
    }
    

    2)在你的AsyncTask中,在onPostExecute()方法结束时,你必须调用canProceed()方法通知JSInterface它可以退出waitForProceed()方法。

    public class MyAsyncTask extends AsyncTask<.......> {
        private JSInterface jsi;
        ... // other class property
    
        public MyAsyncTask(JSInterface jsi) {
            ...
            //do what you want with other class property
    
            this.jsi = jsi;
        }
    
        @Override
        public ... doInBackground(...) {
            ...
            //do something
        }
    
        @Override
        public void onPostExecute(...) {
            ...
            //do something
    
            jsi.canProceed();
        }
    }
    

    3) 在您的 Activity 中,您必须将 JSInterface 对象关联到您的 WebView:

    WebView mWebView;
    
    ...
    
    mWebView.getSettings().setJavaScriptEnabled(true);
    mWebView.addJavascriptInterface(new JSInterface(), "JSIface");
    

    4) 最后,在 JS 中,你可以调用 AsyncTask(我不知道你怎么称呼它,但我猜你使用类似 JSInterface 的东西)并在调用 waitForProceed() 方法之后:

    startAsyncTask(); //somehow
    JSIface.waitForProceed();
    

    希望它能解决你的问题;)

    【讨论】:

      【解决方案3】:

      这是一个详细的例子:

      让我们创建一些接口,当AsyncTask 完成这些东西时应该调用它,例如当onPostExecute 调用时。

      在我的例子中,我们获取一些 JSONArray 数据

      MyTaskListenerItf.java

      public interface GroupTaskListenerItf {
         public void onTaskDone(JSONArray groupArray);
      }
      

      AsyncTask 的模板看起来像:

      MyBuildTask.java

      public class MyBuildTask extends AsyncTask<Void, Void, SomeData>{
      
          private MyTaskListenerItf mTl = null;
      
          public MyBuildTask(Context context,  MyTaskListenerItf tl) {
              super();
              this.mContext = context;        
              this.mTl = tl;
          }
      
             @Override
             protected SomeData doInBackground(Void... params) {
                /* ... */
              }
      
          @Override
          protected void onPostExecute(WmTransferItem transferItem) {
             // ...
      
      
              if(this.mTl != null){           
                  JSONArray data  = new JSONArray("");            
                  this.mTl.onTaskDone(data);
              }      
      
             // ..
           }
      }
      

      所以现在我们的CordovaPlugin 类应该如下所示:

      MyCordovaPlugin.java

      public class MyCordovaPlugin extends CordovaPlugin implements GroupTaskListenerItf {
      
             // we need this callback when Task will finish
         private CallbackContext mMyCallbackContext = null; 
      
         @Override
         public boolean execute(String action, JSONArray args,CallbackContext callbackContext) throws JSONException {
                if("runMe".equals(action)){
                   final GroupTaskListenerItf gt = this;
      
                    mMyCallbackContext = callbackContext;
                   // pass our 'GroupTaskListenerItf' interface to async class    
                    MyBuildTask task = new MyBuildTask(cordova.getActivity(), gt);
                    task.execute();
      
              PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT);
              pluginResult.setKeepCallback(true);
              callbackContext.sendPluginResult(pluginResult); 
                }
                else{
                    this.cordova.getThreadPool().execute( new Runnable() {
                         public void run() {
                           // BTW, here you might run something else out of UI Thread
                          }
                   });
                }
         }
      
      /* ... */
      
       @Override
      public void onTaskDone(JSONArray data) {
      
      if (this.mGroupCallbackContext != null) {
              PluginResult result = new PluginResult(PluginResult.Status.OK, data);
              result.setKeepCallback(false);
              this.mMyCallbackContext.sendPluginResult(result);
            }     
      }
      

      就是这样。

      希望对某人有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-27
        相关资源
        最近更新 更多