[英]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);
}
对于这种需求,您应该做的是:
Callable
提交到线程池 例如,使用这样的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.