Handler
、
Looper
或
runOnUiThread()
方法。
Handler
和
Looper
用于在主
线程与其他线程间传递消息,而
runOnUiThread()
则直接在主线程执行代码。
1、进程:在Android中,一个应用程序通常运行在一个独立的进程中,每个进程有自己的内存空间和生命周期,进程之间通过IPC(进程间通信)机制进行数据交换,组件(如Activity、Service)可以通过android:process
属性指定运行的进程。
2、线程:线程是CPU调度和分派的基本单位,一个进程可以包含多个线程,在Android中,默认情况下所有组件的操作都在主线程(UI线程)中完成,但耗时操作应在后台线程中执行以避免阻塞UI线程。
1、Handler机制
原理:Handler允许发送和处理Message对象或Runnable对象,通过Looper、MessageQueue等实现线程间的通信。
使用步骤:
创建Handler对象时关联到当前线程的Looper。
在子线程中通过Handler发送Message或Runnable到主线程的消息队列。
主线程的Looper不断轮询消息队列,获取并处理消息。
示例代码:
new Thread(new Runnable() { @Override public void run() { Message message = handler.obtainMessage(); message.obj = "Hello from worker thread"; handler.sendMessage(message); } }).start();
2、AsyncTask机制
原理:AsyncTask是一个抽象类,允许在后台线程执行任务并在任务完成后将结果返回到UI线程。
使用步骤:
继承AsyncTask类并实现doInBackground方法(在后台线程执行)。
实现onPostExecute方法(在UI线程执行,用于更新UI)。
调用execute方法开始异步任务。
示例代码:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> { protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls[i]); publishProgress((int) ((i / (float) count) 100)); if (isCancelled()) break; } return totalSize; } protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } protected void onPostExecute(Long result) { showDialog("Downloaded " + result + " bytes"); } }
1、问题:为什么不能在非UI线程中直接更新UI?
解答:因为Android的UI线程是非线程安全的,应用更新UI是调用invalidate()
方法来实现界面的重绘,而invalidate()
方法是非线程安全的,如果在非UI线程来更新UI,可能会导致界面更新的不同步或出现异常。
2、问题:如何选择合适的线程间通信方式?
解答:如果需要在后台执行耗时操作并在完成后更新UI,且不需要频繁通信,可以选择AsyncTask;如果需要在子线程和UI线程之间频繁通信,传递大量数据或需要更灵活的控制,可以选择Handler机制。