繁体   English   中英

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

[英]How to return a string from another thread?

我想从另一个线程返回一个字符串“ 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;
}

但这行不通。 如何正确制作?

 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. 创建一个线程池
  2. 将您的任务作为Callable提交到线程池
  3. 得到结果

例如,使用这样的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);
}

注意:不能在每次调用时都创建线程池,必须在类中为所有线程一次创建线程池,以便在每次调用时重用线程池。

您尚未完全清楚要执行的操作,但是我很确定您不希望getImageURL(url)返回,直到获得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");
}

如果出于某种原因您认为需要在此处使用线程,则应在另一个问题中再次提出问题,并详细说明您要做什么以及为什么要这样做。


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

好的,该错误并不表示该应用程序在一个线程中做了太多工作。 这意味着GUI调用了您的处理程序功能之一,并且在处理程序返回之前已经花费了太多时间

如果您的事件处理函数未及时返回,则将阻止您的应用程序立即响应用户的下一步操作。 这就是错误消息实际上试图告诉您的内容。

如果处理程序在返回之前仍然需要等待工作完成,则无法通过在其他线程中执行“工作”来修复该问题。 现在是时候了。

解决此类问题的方法是:

  • 您的处理程序将GUI置于某种状态,告诉用户我正在等待任何东西,

  • 然后,您的处理程序启动一个将等待任何内容的后台任务,(注:我不是Android程序员,但是我可以肯定,比创建一个新的裸Thread对象有更好的启动方法。 )

  • 然后您的处理程序返回,

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

  • 同时,即使用户单击某项,您的应用程序仍可以响应用户输入,即使只是弹出一条消息,即“现在不行,我仍在等待任何内容”。

  • 最后,您的后台任务完成,并将事件发布到应用程序的事件队列中(我仍然不是Android程序员,所以我实际上不知道您要使用的方法)来更新UI状态以显示不管最终发生了什么。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM