进程堵塞与优化
所谓的堵塞:
我们知道在android中,不允许在主线程(UI线程)中执行耗时的操作。此时我们肯定会通过新启一个线程来执行这些耗时操作。通过此种方法,即可解决一些耗时操作。但是,并不是就那么简单,此时如果想要更新UI线程中的组件怎么办?在android中我们要知道是不允许主线程之外的线程来操作主线程的,否则将抛出异常。
即我们要遵守两个原则:
1. 不堵塞主线程(UI线程);
2. 不要在主线程之外的线程中调用android UI toolkit。
以下是一个外部线程调用UI组件更新UI的例子,满足了原则1,却没有满足原则2:
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
textView.setText(“I am hello!”);
}
}).start();
}
运行后将抛出异常:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
此时我们改如何解决,这个问题呢?在官方的文档中主要提到了两种解决方法如下:
方法一、
To fix this problem, Android offers several ways to access the UI thread from other threads. Here is a list of methods that can help:
· Activity.runOnUiThread(Runnable)
· View.post(Runnable)
· View.postDelayed(Runnable, long)
使用View.post(Runnable)
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
textView.post(new Runnable() {
public void run() {
textView.setText(“I am hello!”);}
});
}
}).start();
}
方法二、使用AsyncTask
AsyncTask其实就是对上面方法的封装,使代码可读性高,更易修改如下例子:
public void onClick(View v) {
new myAsyncTask().execute();//启动一步任务
}
//myAsyncTask的实现
//其实此方法 就是 对 View.post的封装。
private class myAsyncTask extends AsyncTask<String, View, String>{
//长时事件在此方法处理
@Override
protected String doInBackground(String... params) {
Thread.sleep(5000);
String s = "AsyncTaskTest";
return s;
}
//界面的 设置 在这处理
@Override
protected void onPostExecute(String s) {
textView.setText(s);
}
}
现在UI是安全的,代码更简单,因为它分离的部分应该做的工作在一个工作线程的部分应该在UI线程上。
对于AsyncTask的使用,官方文档的说明如下:
你应该阅读AsyncTask的参考,以便充分理解如何使用该类,但是这里是一个快速概述它是如何工作的:
· You can specify the type of the parameters, the progress values, and the final value of the task, using generics
· The method doInBackground() executes automatically on a worker thread
· onPreExecute(), onPostExecute(), and onProgressUpdate() are all invoked on the UI thread
· The value returned by doInBackground() is sent to onPostExecute()
· You can call publishProgress() at anytime in doInBackground() to execute onProgressUpdate() on the UI thread
· You can cancel the task at any time, from any thread