编辑:已解决。对不起,伙计们,我发现虽然我的数据加载发生在后台线程中,但解析数据的回调却没有。解析数据花了很长时间,这就是锁定我的线程的原因。
编辑:我注意到我的首要问题(ProgressDialog不再旋转)可能是由于我使用ProgressDialog而不是阻止UI线程的问题引起的。如果是这种情况,我该如何解决?
编辑:澄清一下,这并不会永远锁定整个程序。加载完所有内容后,将取消进度对话框,并启动新活动。我的问题是,当它加载时,整个UI锁定(即progressdialog停止旋转)
TL; DR:doInBackground()中的Thread.sleep()锁定UI线程
我有一个应用程序,当特定活动打开时,开始从后端加载后台的大量数据,例如,与计划相关的大量数据。此信息不会立即使用,但如果用户尝试访问它(例如,通过单击计划按钮,并启动计划活动),则可以使用此信息。
如果用户在单击“计划”按钮之前等待一点,则会加载所有数据,计划活动将打开,并显示所有内容。我的问题是他们在加载数据之前点击了按钮。
我的解决方案是创建一个显示ProgressDialog的ASyncTask,同时定期检查数据是否已完成加载,否则将睡眠。它知道数据是通过一些应用程序范围的布尔变量完成加载的。我的问题是,即使Thread.sleep()在doinbackground()中运行,它仍然会锁定UI线程。
我使用的是自定义ASyncTask,定义如下:
public class LoadWithProgressDialog extends AsyncTask<Void, Void, Boolean>{
private ProgressDialog pd; //the progress dialog
private String title; //the title of the progress dialog
private String message; //the body of the progress dialog
private Runnable task; //contains the code we want to run in the background
private Runnable postTask; //execute when the task ends
private Context c;
public LoadWithProgressDialog(Context context,String t, String m,Runnable r, Runnable postR){
super();
c = context;
task = r;
postTask = postR;
title = t;
message = m;
}
@Override
protected void onPreExecute(){
pd = ProgressDialog.show(c,title, message, false, false);
}
@Override
protected Boolean doInBackground(Void... params) {
task.run();
return true;
}
@Override
protected void onPostExecute(Boolean result) {
pd.dismiss();
if(postTask != null)
postTask.run();
}
并通过(例如)调用它:
if(loadingSchedule){
LoadWithProgressDialog lwpd = new LoadWithProgressDialog(thisClass,"Loading","Loading Schedule", new Runnable() {
public void run(){
while(loadingSchedule){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},new Runnable() {
public void run(){
Intent i= new Intent(thisClass, Schedule.class);
i.putExtra("numberIneed",index);
startActivity(i);
}
});
lwpd.execute();
(我将对全局变量的访问权限缩短为“loadingSchedule”以便于阅读)
如何使其不锁定UI线程?
答案 0 :(得分:5)
doInBackground()中的Thread.sleep()锁定UI线程
doInBackground()中的Thread.sleep()不会锁定UI线程,正如其名称所述,任务在后台异步执行。
您的UI线程未被锁定。它实际上是在AsyncTask启动之前弹出的ProgressDialog(在onPreExecute()方法中)并且在AsyncTask执行期间(在doInBackground()方法中)继续显示在前面并阻止用户与底层活动的交互。并最终在AsyncTask完成后被解雇。 (在onPostExecute()方法中)
我有一个应用,当特定活动打开时,开始从我的后端加载后台的大量数据
这是一个常见的用例,创建一个在后台加载数据的AsyncTask实现会更高效,而不是创建一个显示ProgressDialog的ASyncTask,同时定期检查数据是否已完成加载,否则会睡眠。 / p>
查看API here,它包含了如何正确使用它的好例子。
答案 1 :(得分:0)
您的代码看起来正确,不应阻止主线程。
所以使用调试器!在lwpd.execute之后将断点放在doInBackground,Thread.sleep,onPostExecute中,您将了解代码的来源和时间。
尝试找到答案&#34;其中UI线程确切被阻止&#34;。