【问题标题】:Android global variable in thread线程中的Android全局变量
【发布时间】:2012-07-25 19:24:08
【问题描述】:

我有问题。这是我的代码:

public String getXmlFromUrl(String url) {
    String xml = null;

        new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                // defaultHttpClient
                DefaultHttpClient httpClient = new DefaultHttpClient();
                HttpGet httpGet = new HttpGet(url);

                HttpResponse httpResponse = httpClient.execute(httpGet);
                HttpEntity httpEntity = httpResponse.getEntity();
                xml = EntityUtils.toString(httpEntity);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                } catch (ClientProtocolException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).run();
    // return XML
    return xml;
}

那么,如何在我的 Thread 中使用 url 以及如何返回 xml?

感谢您的帮助

【问题讨论】:

    标签: java android multithreading variables global


    【解决方案1】:

    Android 提供了一个 AsyncTask,它完全符合您的目标。

    例子:

    private class XMLTask extends AsyncTask<String, String, String> {
        @Override
        protected void onPreExecute() {
            // Do stuff
            // For example showing a Dialog to give some feedback to the user.
        }
    
        @Override
        protected String doInBackground(.. parameters..) {
            try {
                // defaultHttpClient
                DefaultHttpClient httpClient = new DefaultHttpClient();
                HttpGet httpGet = new HttpGet(url);
    
                HttpResponse httpResponse = httpClient.execute(httpGet);
                HttpEntity httpEntity = httpResponse.getEntity();
                xml = EntityUtils.toString(httpEntity);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                } catch (ClientProtocolException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } 
            return xml;
        }
    
        @Override
        protected void onPostExecute(String xml) {
            // If you have created a Dialog, here is the place to dismiss it.
            // The `xml` that you returned will be passed to this method
            xml.Dowhateveryouwant
    
            }
        }
    }
    

    【讨论】:

    • 哦,我可以在 onPostExecute 中返回一些字符串吗?
    • 您的 onPostExecute 接收到由doInBackground() 返回的result 参数。 onPostExecute 可以轮流返回一些 Object。您还必须更改 AsyncTaks&lt;..parameters..&gt; 中的参数。
    • 是的,参数我改了。但是我怎样才能返回一些对象?谢谢。
    • 我不明白:doInBackground() 返回一个布尔值,但 xml 似乎是一个字符串。然后 onPostExecute() 以某种方式看到名为 xml 的变量?谢谢。
    • 更像是伪代码。你可以返回你喜欢的任何东西,并在你喜欢的地方声明你的变量。我更改了它以进行澄清。
    【解决方案2】:

    使url 最终使用它。

    如果您不介意在另一个线程完成之前阻塞,请将xml 变为AtomicReference,并在调用Thread.start() 之后(注意您应该“不”调用Thread.run() - 这不会产生另一个线程),使用一些同步工具(例如CountdownLatch)等到线程完成后再返回xml

    但是如果你不介意阻塞,为什么不直接执行代码而不使用单独的线程呢?如果不能阻止,则不能返回 xml 值 - 您必须更改设计,可能执行 AsyncTask 并异步提供结果。

    【讨论】:

      【解决方案3】:

      您可以将您的 URL 标记为 final 并在 Runnable 中使用它,如下所示:

      public String getXmlFromUrl(final String url) {
          // ...
      }
      

      您可能想要定义一个无状态回调方法或类,您可以调用它来处理您的 XML 响应。你可以这样称呼它:

      xml = EntityUtils.toString(httpEntity);
      handleXmlResponse(xml);
      

      如果您愿意,可以将方法 handleXmlResponse 定义为包含 getXmlFromUrl 方法的类的私有方法。

      您可能需要考虑的一件事是使用 Executors 类来获取 newSingleThreadExecutor 并将您的 Runnable 传递给该类,而不是每次您想要获取一些 XML 时都创建一个新线程:

      https://developer.android.com/reference/java/util/concurrent/Executors.html#newSingleThreadExecutor%28%29

      这是一个例子:

      ExecutorService mThreadPool = Executors.newSingleThreadExecutor();
      public String getXmlFromUrl(String url) {
          String xml = null;
      
              // Note the change here. Everything else remains the same.
              mThreadPool.execute(new Runnable() {
      
                  @Override
                  public void run() {
                      try {
                      // defaultHttpClient
                      DefaultHttpClient httpClient = new DefaultHttpClient();
                      HttpGet httpGet = new HttpGet(url);
      
                      HttpResponse httpResponse = httpClient.execute(httpGet);
                      HttpEntity httpEntity = httpResponse.getEntity();
                      xml = EntityUtils.toString(httpEntity);
                      } catch (UnsupportedEncodingException e) {
                          e.printStackTrace();
                      } catch (ClientProtocolException e) {
                          e.printStackTrace();
                      } catch (IOException e) {
                          e.printStackTrace();
                      }
                  }
              });
          // return XML
          return xml;
      }
      

      【讨论】:

        【解决方案4】:

        两件事:

        • 此方法是同步调用,因此最好使用 AsyncTask。
        • 使用 Thread.start() 启动线程。

        【讨论】:

        • 他需要在后台线程上执行网络I/O,以免卡住主用户界面线程。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-16
        相关资源
        最近更新 更多