我正在制作游戏2048的AI版本。在后台创建游戏树后,我想用asynctask
更新UI。它暂时不起作用。
这是我在AsyncTask
MainActivity.java;
的地方
private class AsyncTaskRunner extends AsyncTask<Void, String, Void> {
@Override
protected Void doInBackground(Void... v) {
try {
Tree tree = new Tree(gameEngine);
List<Node> path;
Node root = new Node(gameEngine.grid.cells);
tree.createInitialTree(root);
path = ai.findPath(root);
Node maxNode = path.get(path.size() - 1);
for (Node node : path) {
SystemClock.sleep(500);
publishProgress(node.getDir());
}
while (!maxNode.myLose && (gameEngine.grid.areCellsAvailable(maxNode.getBoard()) || gameEngine.availableTileMatchLeft(maxNode)
|| gameEngine.availableTileMatchRight(maxNode) || gameEngine.availableTileMatchUp(maxNode) ||
gameEngine.availableTileMatchDown(maxNode))) {
tree = new Tree(gameEngine);
tree.createTree(maxNode);
path = ai.findPath(maxNode);
for (Node node : path) {
SystemClock.sleep(500);
publishProgress(node.getDir());
}
maxNode = path.get(path.size() - 1);
}
System .out.println("You lose!!!");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@SuppressWarnings("unchecked")
@Override
protected void onProgressUpdate(String... direction) {
switch (direction[0]) {
case "left": onLeftSwipe();
break;
case "right": onRightSwipe();
break;
case "down": onDownSwipe();
break;
case "up": onUpSwipe();
break;
}
super.onProgressUpdate(direction);
}
@Override
protected void onPostExecute(Void v) {
}
}
从onCreate()
;
AsyncTaskRunner runner = new AsyncTaskRunner();
runner.execute();
使用publishProggress(path)
,我发送的列表path
具有AI将执行的移动。但是当谈到onProggressUpdate()
并执行onSwipeLeft()
时,它不会更新游戏画面。我正确使用AsyncTask
吗?谢谢你的帮助。
更新:现在正在更新UI
,但不会等待publishProggress()
完成。我该怎么做?
答案 0 :(得分:1)
我不知道为什么你在super.onProgressUpdate(path);
方法中注释了onProgressUpdate
这句话。你不应该这样做。
由于您是第一次使用asynctask
,我将为您提供一个非常简单的示例,可以从asynctask
更新UI组件(textview和进度条)。
public class MainActivity extends ActionBarActivity {
ProgressBar progressBar;
TextView textOut1, textOut2, textOut3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// required codes goes here
}
public class MyAsyncTask extends AsyncTask<Void, Integer, Void>{
@Override
protected void onPreExecute() {
//In UI thread, you can access UI here
super.onPreExecute();
String s1 = textIn1.getText().toString();
textOut1.setText(s1);
}
@Override
protected Void doInBackground(Void... arg0) {
for(int i=0; i<=10; i++){
SystemClock.sleep(1000);
publishProgress(i); //update UI in onProgressUpdate
//Can GET from UI elements
String s2 = textIn2.getText().toString();
final String msgInBackGround = "doInBackground: " + i + " - " + s2;
/*
* Cannot direct SET UI elements in background thread
* so do with runOnUiThread()
*/
runOnUiThread(new Runnable(){
@Override
public void run() {
textOut2.setText(msgInBackGround);
}});
}
return null;
}
@Override
protected void onPostExecute(Void result) {
//In UI thread, you can access UI here
textOut3.setText("onPostExecute");
super.onPostExecute(result);
}
@Override
protected void onProgressUpdate(Integer... values) {
//In UI thread, you can access UI here
progressBar.setProgress(values[0]);
super.onProgressUpdate(values);
}
}
}
希望它会对你有所帮助。您可以在网上找到完整的工作示例。请参阅它们以全面了解asynctask
。
UPDATE :为了在doInBackground()
和publishProgress()
之间实现同步,您可以在某个全局对象上使用同步块,或者您可以使用简单标志来保持{的执行{1}}称为忙等待。
同步阻止:
doInBackground()
忙碌等待 :( 不首选方式)
使用标记protected List<Data> doInBackground(String... params) {
synchronize(data) // data is some global object
{
// do some job 1
publishProgress(); // wait until the progress finish
//do some job 3
}
}
protected void onProgressUpdate(Void... values) {
synchronize(data) // data is the same global object
{
// do some job
}
}
然后调用发布进度。请忙于在_publishFinished = false;
等待,如下所示。
doInBackground()
在onProgressUpdate调用结束时
if(!_publishFinish){
Thread.Sleep(200); // busy waiting
}