use*_*245 2 multithreading android process android-service android-asynctask
在android中我们为什么要使用asyntask和service,而不是使用新的thread()并编写必要的后台功能?
我知道我们不应该运行长时间运行的操作,比如在mainthread即UI线程上从服务器下载文件.并且应该使用asynctask或服务.
但是为什么我们不能创建一个新的thread(){最终是一个除主线程之外的新线程}并在该线程中编写必须长时间运行的操作.
谷歌为什么创建AsyncTask和服务而不建议使用常规的新线程()?
提前致谢
编辑1:可能是我不清楚我的问题或不确定,如果我,即使现在.帮帮我.
我明白了,整点都是从
Do not block the UI thread
Do not access the Android UI toolkit from outside the UI thread
Run Code Online (Sandbox Code Playgroud)
为什么?1. UI线程可以处理多少?我们如何确定断点?如何确定ANR点?我们能跟踪吗?
2.当服务组件处理长时间运行的操作时,为什么活动组件不能处理?
请记住,如果你使用一个服务,它仍然在默认情况下,你的应用程序的主线程中运行,所以你还是应该在服务中创建一个新的线程,如果它执行密集或阻塞操作 http://developer.android.com/guide/ components/services.html 上面的语句来自android文档.
3.如果我们如此关注主线程,我们是否可以立即开始新的线程?不要误解我的问题3,我试图了解在主线程中启动服务的优势.默认情况下.
在上面的语句中,它是否表明主线程能够启动和处理服务的长时间运行负载?如果是这样,它与问题1相矛盾.
那么让我们来看看你如何使用Thread执行一个简单的任务.
第一步是使用Runnable创建一个Thread.像这样的东西:
private void fetchResultsAsync() {
Runnable runner = new Runnable() {
@Override
public void run() {
List<String> results = fetchResultsFromWebServer();
}
};
new Thread(runner).run();
}
Run Code Online (Sandbox Code Playgroud)
问题是,我们需要显示结果,所以它实际上更像是这样:
private void fetchResultsAsync() {
Runnable runner = new Runnable() {
@Override
public void run() {
List<String> results = fetchResultsFromWebServer();
workFinished(results);
}
};
new Thread(runner).run();
}
private void workFinished(List<String> results) {
// show the results on the UI
}
Run Code Online (Sandbox Code Playgroud)
它看起来不错,但是有一个问题; 回调方法(workFinished)必须更新UI.如果我们从任何非主线程执行此操作,将会出现大问题.我们需要一种线程安全的方法来调用该方法,这就是Handlers的用途.我们还提出了一种更新进度的方法,这是非常常见的.代码现在看起来像这样:
private final Handler myHandler = new Handler();
private void fetchResultsAsync() {
Runnable runner = new Runnable() {
@Override
public void run() {
List<String> results = fetchResultsFromWebServer();
workFinished(results);
}
};
new Thread(runner).run();
}
private void showProgress(int result) {
myHandler.post(new Runnable() {
@Override
public void run() {
// update a progress bar here
}
});
}
private void workFinished(final List<String> results) {
myHandler.post(new Runnable() {
@Override
public void run() {
// show the results on the UI
}
});
}
Run Code Online (Sandbox Code Playgroud)
将此与使用AsyncTask的实现进行比较:
private void fetchWithTask() {
new AsyncTask<Void, Integer, List<String>>() {
@Override
protected List<String> doInBackground(Void... params) {
return fetchResultsFromWebServer();
}
@Override
protected void onPostExecute(List<String> strings) {
// show the results on the UI
}
@Override
protected void onProgressUpdate(Integer... values) {
// update a progress bar here
}
}.execute();
}
Run Code Online (Sandbox Code Playgroud)
它与代码行没有太大差别,但更明显的是需要发生什么以及在哪里发生.它可以保护您免受令人讨厌的错误,比如忘记在必须发布到UI-Thread拥有的Handler的Runnable中包含UI触摸代码.
现在想象一下,您需要执行几种不同类型的小后台任务.从错误的后台线程调用错误的showProgress或workFinished方法会非常容易,因为你必须自己将所有这些部分插入.
使用Handler的默认构造函数时,潜伏着一个非常讨厌的bug.如果在运行时期间非UI线程首次引用包含类,则Handler将属于该Thread.AsyncTask隐藏总是在正确的线程上做事情.这很难抓住!
乍一看AsyncTasks看起来并不是那么有用,但回调管道是他们真正在黑桃中得到回报的地方.
| 归档时间: |
|
| 查看次数: |
636 次 |
| 最近记录: |