编辑:有人建议添加我的代码会很有帮助,我的AsyncTask代码现在粘贴在下面......
我刚刚学习Android,而且我有一个带有几个按钮的用户界面。我想按顺序为UI设置动画,更改按钮的颜色。
当然,我不应该从主线程中做到这一点,而且无论如何它都不起作用。操作UI的代码会运行,但UI不会更新,直到序列结束。
所以我创建了一个线程并尝试从后台线程运行序列,但是,我会在尝试从后台线程中操作UI组件时出错。只有主线程可以触摸UI组件。
然后我发现了AsyncTask。我想的是,我可以在doInBackground()中运行序列。每次我需要更新UI时,我都会调用publishProgress(),这会导致从主线程调用onProgressUpdate(),这样我就可以毫无错误地访问UI组件。
每当我调用publishProgress()时,我都会使用SystemClock.sleep(500)跟随它,让时间过去,直到下一个动画UI更新。
我发现doInBackground()会在大约2秒内(每个500毫秒)运行4个UI状态更改,但每次调用publishProgress()时UI都不会更新。而是doInBackground()完成,然后连续4次调用onProgressUpdate()。
从描述中可以看出,发布进度和出版物onProgressUpdate旨在更新进度条,因为doInBackground通过一些长时间运行的任务进行曲柄处理,因此,显然onProgressUpdate必须在doInBackground完成之前执行多次,对吧?
我错过了什么吗?
公共类MainActivity扩展了AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startGame(View view) {
MyTask task = new MyTask();
task.doInBackground();
}
class MyTask extends AsyncTask<Void,Void,Void> {
private int current_int;
@Override
protected Void doInBackground(Void... voids) {
this.current_int = 1;
Log.e("doInBackground","light up button "+this.current_int);
publishProgress();
SystemClock.sleep(500);
this.current_int = 2;
Log.e("doInBackground","light up button "+this.current_int);
publishProgress();
SystemClock.sleep(500);
this.current_int = 1;
Log.e("doInBackground","light up button "+this.current_int);
publishProgress();
SystemClock.sleep(500);
this.current_int = 2;
Log.e("doInBackground","light up button "+this.current_int);
publishProgress();
SystemClock.sleep(500);
return null;
}
@Override
protected void onProgressUpdate(Void... voids) {
super.onProgressUpdate(voids);
Log.e("onProgressUpdate","Updating button "+this.current_int);
Button btn1 = (Button) findViewById(R.id.button1);
Button btn2 = (Button) findViewById(R.id.button2);
if (this.current_int==1){
btn1.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_light));
btn2.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_dark));
} else {
btn2.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_light));
btn1.setBackgroundColor(getResources().getColor(android.R.color.holo_blue_dark));
}
}
}
}
答案 0 :(得分:1)
仅供参考:Asynctask提供了一种从主线程(调用线程)转换到新线程(称为线程)的系统方法。 onPreExecute()和 onPostExecute()方法在调用线程上执行, doInBackground()是实际的在新线程上执行的方法。因此,如果从 doInBackground()方法完成,则在主线程上执行UI更新将导致异常。
因此,您的核心背景逻辑应放在 doInBackground()方法中。
如果要从后台线程(Asynctask或其他)更新UI,可以使用以下命令来执行:
YourActivity.this.runOnUiThread(new Runnable(){
@Override
public void run()
{
//UI update operations here
}
});
答案 1 :(得分:0)
您可以使用Handler
,
public class TestClass extends AsyncTask<Void,Void,Void> {
boolean isRunning = true; //set false after executing UI logic.
Handler mHandler = new Handler();
@Override
protected Void doInBackground(Void... params) {
YourFunctionToUpdateUI();
return null;
}
public void YourFunctionToUpdateUI()
{
new Thread(new Runnable() {
@Override
public void run() {
while (isRunning) {
try {
mHandler.post(new Runnable() {
@Override
public void run() {
// your code to update the UI.
}
});
} catch (Exception e) {
//handle exception
}
}
}
}).start();
}
}
答案 2 :(得分:0)