如何从另一个线程返回一个字符串?

时间:2016-06-19 18:09:06

标签: java android multithreading return

我想从另一个线程返回一个字符串“finalurl”,如下所示:

public String getImageURL(String url) {

    final String finalUrl = url;

    Thread t1 = new Thread(new Runnable() {
        public void run() {
            Document doc = null;
            try {
                doc = Jsoup.connect(finalUrl).get();
            } catch (IOException e) {
                e.printStackTrace();
            }
            Element masthead = doc.select("div.post-image").select("img[src~=(?i)\\.(png|jpe?g)]").first();
            finalUrl = masthead.absUrl("src");
        }
    });

    t1.start();
    return finalUrl;
}

但它不起作用。如何正确使用?

3 个答案:

答案 0 :(得分:1)

 return finalUrl;

此代码永远不会返回您想要的字符串。

您需要通过众多技术之一修复您的逻辑。最简单的方法是使用处理程序。像这样:

private static final int URL_MESSAGE = 1;

private final Handler handler = new Handler(Looper.getMainLooper()) {

    @Override
    public void handleMessage(Message message) {
        super.handleMessage(message);
        if (message.arg1 == URL_MESSAGE) {
            final Object obj = message.obj;

            if (obj instanceof String) {
                String url = (String) obj;
            }
        }
    }
};

private final Runnable runnable = new Runnable() {
    public void run() {
        Document doc = null;
        try {
            doc = Jsoup.connect(finalUrl).get();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Element masthead = doc.select("div.post-image").select("img[src~=(?i)\\.(png|jpe?g)]").first();
        String finalUrl = masthead.absUrl("src");

        Message message = new Message();
        message.arg1 = URL_MESSAGE;
        message.obj = finalUrl;
        handler.sendMessage(message);
    }
};

@Override
protected void onDestroy() {
    super.onDestroy();
    handler.removeCallbacks(runnable);
}

private void execute() {
    handler.post(runnable);
}

答案 1 :(得分:1)

对于这种需要,你应该做的是:

  1. 创建线程池
  2. 将您的任务作为Callable提交给线程池
  3. 获取结果
  4. 使用Executors创建您的线程池,例如:

    // Create a thread pool composed of only four threads in this case
    private final ExecutorService executor = Executors.newFixedThreadPool(4);
    

    Callable

    提交您的任务
    final Future<String> future = executor.submit(new Callable<String>() {
        @Override
        public String call() throws Exception {
            Document doc = Jsoup.connect(url).get();
            Element masthead = doc.select("div.post-image")
                .select("img[src~=(?i)\\.(png|jpe?g)]").first();
            return masthead.absUrl("src");
        }
    });
    

    获取结果

    try {
        return future.get();
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        throw new RuntimeException(e);
    } catch (ExecutionException e) {
        throw new RuntimeException(e);
    }
    

    NB:不能在每次调用时创建线程池,必须为您的所有类创建一次线程池,以便在每次调用时重用它。

答案 2 :(得分:0)

您还没有明确说明您要做什么,但我很确定您不希望您的getImageURL(url)返回,直到它获得为止一个网址。

正确的方法是不使用线程

public String getImageURL(String url) {
    Document doc = null;
    try {
        doc = Jsoup.connect(finalUrl).get();
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
    Element masthead = doc.select("div.post-image").select("img[src~=(?i)\\.(png|jpe?g)]").first();
    return masthead.absUrl("src");
}

如果您认为自己需要在此处使用某个帖子,那么您应该在另一个问题中再次提问,并更详细地解释您尝试做什么以及为什么要这样做做到这一点。

  

错误说:&#34; 06-18 21:22:12.701 7816-7816 / pl.dariusz.app I / Choreographer:跳过39帧!应用程序可能在其主线程上做了太多工作。&#34;

好的,该错误并不意味着应用程序在一个线程中执行了太多工作。这意味着GUI调用了一个处理函数,并且在处理程序返回之前已经过了 time

如果您的事件处理函数没有及时返回,它将阻止您的应用程序及时响应用户下一步做什么。这就是错误信息真正试图告诉你的内容。

你可以通过做&#34;工作&#34;来解决这个问题。在其他一些线程中,如果你的处理程序仍然需要在返回之前等待工作完成。重要的是时间

解决此类问题的方法是:

  • 你的处理程序将GUI置于某种告诉用户的状态,我等着什么,

  • 然后你的处理程序启动一个等待任何事情的后台任务,(注意:我不是Android程序员,但我很确定那里有更好的方法启动任务而不是创建一个新的裸Thread个对象。)

  • 然后您的处理程序返回

  • 您的后台任务在其他线程中运行,例如Jsoup.connect(finalUrl).get();

  • 与此同时,如果用户点击某些内容,您的应用仍然可以响应用户输入,即使它只是弹出一条消息,显示,&#34;现在不是,我&# 39;我还在等什么。&#34;

  • 最后,您的后台任务完成,并将其发布到应用程序的事件队列(我还不是Android程序员,所以我实际上并不知道什么方法你打电话来做那件事会更新UI状态,以显示最终发生的事情。