使用 AsyncTask 会使应用程序变慢
Posted
技术标签:
【中文标题】使用 AsyncTask 会使应用程序变慢【英文标题】:Using AsyncTask makes the app slower 【发布时间】:2014-10-05 16:43:54 【问题描述】:我有这个problem,你建议使用 AsyncTask 或 Service。 所以现在我第一次使用了一个 AsyncTask 类,我在其中添加了用于下载和解析 JSON 文件的代码。代码如下:
public class HomePage extends Activity
private Database db = new Database(this);
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.homepage);
new DownloadDataFromServer().execute(new String[] "http://www.example.com/data.json" );
protected void onDestroy()
super.onDestroy();
db.close();
// Async Task Class
private class DownloadDataFromServer extends AsyncTask<String, Integer, String>
ProgressDialog dialog;
@Override
protected void onCancelled()
super.onCancelled();
@Override
protected void onPreExecute()
dialog = new ProgressDialog(HomePage.this);
dialog.setIndeterminate(false);
dialog.setMax(100);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setCancelable(true);
dialog.setTitle("Download JSON");
dialog.setMessage("Please wait..");
dialog.show();
super.onPreExecute();
@Override
protected String doInBackground(String... urls)
int count = 0;
int lenghtOfFile = 0;
// JSON DOWNLOADING AND PARSING
SQLiteDatabase dbr = db.getReadableDatabase();
try
StrictMode.ThreadPolicy policy= new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(urls[0]);
request.addHeader("Cache-Control", "no-cache");
long id = -1;
HttpResponse response = client.execute(request);
HttpEntity entity = response.getEntity();
InputStreamReader in = new InputStreamReader(entity.getContent());
BufferedReader reader = new BufferedReader(in);
StringBuilder stringBuilder = new StringBuilder();
String line = "";
while ((line=reader.readLine()) != null)
stringBuilder.append(line);
JSONArray jsonArray = new JSONArray(stringBuilder.toString());
SQLiteDatabase dbWrite = db.getWritableDatabase();
ContentValues values = new ContentValues();
dbr.delete("users", "1", null);
long total = 0;
lenghtOfFile = jsonArray.length();
for (int i = 0; i < lenghtOfFile; i++)
JSONObject jObj = (JSONObject) jsonArray.getJSONObject(i);
values.put("_id", jObj.optString("id").toString());
values.put("city", jObj.optString("city").toString());
values.put("name",jObj.optString("name").toString());
id = dbWrite.insert("users", null, values);
count++;
total += count;
onProgressUpdate((int) ((total * 100) / lenghtOfFile));
catch (ClientProtocolException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
catch (JSONException e)
e.printStackTrace();
return lenghtOfFile+"";
protected void onProgressUpdate(Integer... progress)
dialog.setProgress(progress[0]);
@Override
protected void onPostExecute(String result)
if (Integer.parseInt(result) < 0)
Toast.makeText(getBaseContext(), "Failed!", Toast.LENGTH_SHORT).show();
else
Toast.makeText(getBaseContext(), result + " users", Toast.LENGTH_SHORT).show();
dialog.dismiss();
达到 100% 需要很长时间,差不多 1 分钟! 除了进度条在 0% 上挂了一会儿,然后它只显示 100%。 可能是什么问题?
【问题讨论】:
你不应该直接打电话给onProgressUpdate()
。相反,请致电publishProgress()
,这将致电onProgressUpdate()
Urrrm,顺便说一句,摆脱你的 StrictMode
东西。我假设它之前在主线程上运行代码时就在那里。
@Squonk 不错! smartmouse,see the docs,关于使用 StrictMode,如果您不知道,请不要将其留在生产版本中。
你说得对,我删除了那 2 行,但它仍然有效。谢谢。
无论如何,主要问题仍然存在:应用程序加载非常缓慢,在等待期间 LogCat 显示:08-12 17:07:46.720: I/Timeline(16921): Timeline: Activity_idle id: android.os.BinderProxy@41b6f398 time:24548374 08-12 17:08:01.525: I/Timeline(16921): Timeline: Activity_idle id: android.os.BinderProxy@41b6f398 time:24563177
【参考方案1】:
这是因为每个 insert()
在 DB 中进行自己的事务。您必须将所有 insert()
调用包装在一个事务中,如下所示:
dbWrite.beginTransaction();
try
//put all insert() here
dbWrite.setTransactionSuccessful();
catch
//Error in between database transaction
finally
dbWrite.endTransaction();
祝你好运! :)
另外,您应该使用publishPorgress 方法更新ProgressDialog,而不是直接调用onProgressUpdate
【讨论】:
在使用 AsyncTask 之前,我使用一种方法进行了相同的操作,并且等待时间没有问题。那么为什么使用 AsyncTask,我在其中添加相同的操作,需要这么长时间?实际上,如果我向“id = dbWrite.insert("users", null, values);" 添加注释,则问题不在于每个 insert()我遇到了同样的问题... 我错了,如果我评论 insert() 进度条加载速度很快。所以我在我的代码中应用了你的提示,现在它加载速度很快。非常感谢! 你能解释一下为什么它运作良好吗?在使用 AsyncTask 之前我不需要这个提示,为什么现在我必须使用事务? 一般来说,您已经在每个 insert() 操作上使用了隐式事务。事务对于 db 来说是相当困难的操作(打开、应用、完成)。这样,您只需创建一个事务。实际上,我不知道您为什么在 UI 线程上没有性能问题。你必须有!对于您确实拥有的大数据集。 顺便说一句,有关交易的更多信息,您可以在那里找到:tutorialspoint.com/sql/sql-transactions.htm【参考方案2】:要更新AsyncTask
的进度,您应该调用publishProgress 方法。
不要直接拨打onPublishProgress
。
【讨论】:
以上是关于使用 AsyncTask 会使应用程序变慢的主要内容,如果未能解决你的问题,请参考以下文章