我曾经接触过 Handlers 和 runOnUiThread 的概念。但对我来说,它们之间的区别仍然存在疑惑。
它们都旨在从后台线程执行UI操作。但是,在选择两种方法之间需要考虑哪些因素。
例如,考虑一个在后台执行Web服务的Runnable
Thread
,现在我想更新UI。
更新UI的最佳方式是什么?我应该选择Handler
还是runOnUiThread
?
我仍然知道我可以使用AsyncTask
并利用onPostExecute
。但我只是想知道它们之间的区别。
我曾经接触过 Handlers 和 runOnUiThread 的概念。但对我来说,它们之间的区别仍然存在疑惑。
它们都旨在从后台线程执行UI操作。但是,在选择两种方法之间需要考虑哪些因素。
例如,考虑一个在后台执行Web服务的Runnable
Thread
,现在我想更新UI。
更新UI的最佳方式是什么?我应该选择Handler
还是runOnUiThread
?
我仍然知道我可以使用AsyncTask
并利用onPostExecute
。但我只是想知道它们之间的区别。
Activity.runOnUiThread()是更通用的Handlers的特殊情况。使用Handler
,您可以在自己的线程中创建自己的事件查询。使用使用default constructor实例化的Handlers
并不意味着“代码将在UI线程上运行”。默认情况下,处理程序绑定到它们从中实例化的Thread
。
要创建一个保证绑定到UI(主)线程的Handler
,您应该创建一个绑定到Main Looper的Handler
对象,如下所示:
Handler mHandler = new Handler(Looper.getMainLooper());
runOnUiThread()
方法的实现,它使用Handler
来执行操作: public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
runOnUiThread()
,则Runnable action
将立即执行。否则,它将被发布到Handler
,稍后将被执行。new Handler(Looper.getMainLooper())
。 - HitOdessitLooper.getMainLooper()
这句话在我遇到一个毫无头绪的问题时给了我很大的帮助。(http://stackoverflow.com/questions/22831612/cant-handle-ui-after-reconnecting-to-the-server) - Muhammed RefaatrunOnUiThread()
是在UI线程中调用的,它将立即运行action
。否则,它将把action
发布到Handler。 - Ken处理程序是旧的方式(API级别1)来完成任务,然后引入了AsycTask
(API级别3),并更加强调使用runOnUIThread
(API级别1)。您应该尽可能避免使用处理程序,并根据需要选择其他两种方法。
Runnable
需要更新UI,那么请在runOnUiThread
上发布它。Runnable
。Runnable
发布到UI线程。它会抛出android.os.NetworkOnMainThreadException
这些类型的Runnable
应该在不同的线程上运行,比如HandlerThread。完成操作后,你可以使用与UI线程关联的Handler
将结果发布回UI线程。public void onClick(View view) {
// onClick on some UI control, perform Network or IO operation
/* Create HandlerThread to run Network or IO operations */
HandlerThread handlerThread = new HandlerThread("NetworkOperation");
handlerThread.start();
/* Create a Handler for HandlerThread to post Runnable object */
Handler requestHandler = new Handler(handlerThread.getLooper());
/* Create one Handler on UI Thread to process message posted by different thread */
final Handler responseHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
//txtView.setText((String) msg.obj);
Toast.makeText(MainActivity.this,
"Runnable on HandlerThread is completed and got result:"+(String)msg.obj,
Toast.LENGTH_LONG)
.show();
}
};
NetworkRunnable r1 = new NetworkRunnable("http://www.google.com/",responseHandler);
NetworkRunnable r2 = new NetworkRunnable("http://in.rediff.com/",responseHandler);
requestHandler.post(r1);
requestHandler.post(r2);
}
class NetworkRunnable implements Runnable{
String url;
Handler uiHandler;
public NetworkRunnable(String url,Handler uiHandler){
this.url = url;
this.uiHandler=uiHandler;
}
public void run(){
try {
Log.d("Runnable", "Before IO call");
URL page = new URL(url);
StringBuffer text = new StringBuffer();
HttpURLConnection conn = (HttpURLConnection) page.openConnection();
conn.connect();
InputStreamReader in = new InputStreamReader((InputStream) conn.getContent());
BufferedReader buff = new BufferedReader(in);
String line;
while ((line = buff.readLine()) != null) {
text.append(line + "\n");
}
Log.d("Runnable", "After IO call:"+ text.toString());
Message msg = new Message();
msg.obj = text.toString();
/* Send result back to UI Thread Handler */
uiHandler.sendMessage(msg);
} catch (Exception err) {
err.printStackTrace();
}
}
}
Handler 有许多工作,例如消息传递和频繁的 UI 更新,如果您为任何正在运行的任务启动 A Thread。Handler 允许您发送和处理与线程的 MessageQueue 相关联的 Message 和 Runnable 对象,这在许多应用程序中非常有用,如蓝牙聊天、wifi 聊天等。而且 Handler 还有 PostDelay 和 PostAtTime 方法,可以让您玩弄任何视图以进行动画和更改可见性等操作。
您一定要看看这个。
http://developer.android.com/guide/components/processes-and-threads.html
http://developer.android.com/tools/testing/activity_testing.html
以下是HitOdessit的回答。
你可以创建一个类,如下所示。
public class Global{
private static Handler mHandler = new Handler(Looper.getMainLooper());
public static void runOnUiThread(Runnable action){
mHandler.post(action);
}
}
Global.runOnUiThread(new Runnable(){
//Your code
});
这可以在任何地方运行(只要您可以访问全局类)。
runOnUiThread
只是将一个Runnable
对象发布到Handler
上的一种快捷方式。Handler
是Android中定义的跨线程通信设施的基础(例如,AsyncTask
的onPostExecute
使用Handler
来传递doInBackground
的结果)。 - zapl