然而,使用Xamarin.Android,我不认为这是我的问题背后的原因。
我面临的问题是OnProgressUpdate方法只能在AsyncTask对象中使用句柄后台任务调用一次。这是我的班级:
public class DBInflater : AsyncTask
{
private int progress;
private ProgressBar progressBar;
public DatabaseInflater(ProgressBar progressBar)
{
this.progressBar = progressBar;
}
protected override void OnPreExecute()
{
base.OnPreExecute();
}
protected override Java.Lang.Object DoInBackground(params Java.Lang.Object[] @params)
{
System.Threading.Tasks.Task.Run([some heavy task]);
while (progress < 100)
{
Java.Lang.Thread.Sleep(500);
PublishProgress(progress);
progress += 1;
}
return true;
}
protected override void OnProgressUpdate(params Java.Lang.Object[] values)
{
progressBar.Progress = progress;
}
protected override void OnPostExecute(Java.Lang.Object result)
{
base.OnPostExecute(result);
}
}
我设法将问题缩小到这条线:Java.Lang.Thread.Sleep(500); 如果我使用较小的值进行睡眠,OnProgressUpdate将在第一次调用后不被调用。我登陆500,因为有了这个值,OnProgressUpdate会被正确调用,并且progressBar会在屏幕上更新。
我有必要以一定的间隔睡眠线程吗?我希望progressBar能够实时更新,而不是每半秒更新一次。
答案 0 :(得分:3)
在Task
方法中的DoInBackground
线程中运行不报告其进度的内容没有任何意义。
当调用DoInBackground
时,您不在UI线程上而是在后台线程中,您可以通过检查Looper.MainLooper.IsCurrentThread
的值进行检查,因此不需要使用Task.Run
。
因此,一旦进入DoInBackground
,您的DB Inflater
将会执行一系列步骤,创建数据库,创建表,索引等等。然后使用数据等加载每个表...您可以自行决定已发生的进度并将其发布(PublishProgress
)。
在这个例子中,我有三个步骤,并在完成每个步骤后报告竞争增加了33%。
public class DBInflaterAsyncTask : AsyncTask
{
protected override Object DoInBackground(params Object[] @params)
{
// You are not on the UI thread
Task.Delay(1000); // create db
PublishProgress(new Object[] { 33 });
Task.Delay(1000); // create tables
PublishProgress(new Object[] { 66 });
Task.Delay(1000); // load table data
PublishProgress(new Object[] { 99 });
return null;
}
protected override void OnProgressUpdate(params Object[] values)
{
// You are on the UI thread
Log.Debug("SomeTag", values[0].ToString());
}
}