我想用AsyncTask初始化游戏引擎的所有组件。有人可以指导我如何做到这一点吗?
我想要这样的东西:1. 在代码运行之前,设置初始屏幕 (.xml)2. 运行初始化代码3.完成所有操作后,运行游戏的加载屏幕
这是我当前的代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Display splash screen
if(this.splashScreen != null) {
// .xml
setContentView(this.splashScreen);
}
// Do all the initialization
// Acquire a wakeLock to prevent the phone from sleeping
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "GLGame");
// Setup all the Game Engine components
gameEngineLog = new WSLog("WSGameEngine");
gameEngineLog.setLogType(this.gameEngineLogType);
gameLog = new WSLog(this.gameLogTAG);
gameLog.setLogType(this.gameLogType);
io = new FileIO(this, getAssets());
audio = new Audio(this);
wsScreen = new WSScreen(this, this.screenResizeType, this.customTopYGap, this.customLeftXGap, this.gameScreenWidth, this.gameScreenHeight);
graphics = new Graphics(this, wsScreen.getGameScreen(), wsScreen.getGameScreenextended());
renderView = new RenderView(this, wsScreen.getGameScreen(), wsScreen.getGameScreenextended(), FPS, maxFrameskippes);
input = new Input(this, renderView, logGameEngineInputLog);
networkSocket = new NetworkSocket(this);
this.gameEngineLog.d(classTAG, "Completed initialization");
setContentView(renderView);
// Check that the developer has initialized the assets
if(this.assets == null) {
this.gameEngineLog.w(classTAG, "The assets for the game haven't been defined!");
}
this.getNetworkSocket().useAnalytics(this.analyticsAppAPIKey);
this.getNetworkSocket().useServerCommunication(this.serverCommunicationAppID, this.serverCommunicationClientKey);
this.getNetworkSocket().useFacebookCommunicaiton(this.facebookCommunicationAppID);
// Check if server communication should be initialized
if(this.networkSocket.getUseOfServerCommunication() == true) {
this.networkSocket.getServerCommunication().initialize(this, this.networkSocket.getServerCommunicationAppID(), this.networkSocket.getServerCommunicationClientKey());
}
// Check if facebook communication should be initialized
if(this.networkSocket.getUseFacebookCommunication() == true) {
this.networkSocket.getFacebookCommunication().initialize(this.networkSocket.getFacebookCommunicationAppID(), true);
}
// Start the Load screen
// Once all of this code has been executed, the class that extends this class calls "setScreen(new LoadScreen(this));" to set the LoadScreen, which
// loads all the assets of the game
}
根据 asynctask 文档,该类公开了四种可用于实现应用程序加载逻辑的方法:
onPreExecute(),在任务后立即在 UI 线程上调用执行。此步骤通常用于设置任务,例如通过在用户界面中显示进度条。
doInBackground(Params...),在后台线程上调用在 onPreExecute() 完成执行后立即执行。此步骤是用于执行可能需要很长时间的后台计算。
onProgressUpdate(Progress...),在调用后在 UI 线程上调用以发布进度(进度...)。此方法用于显示任何用户界面中进度的形式,而背景计算仍在执行。
onPostExecute(Result),在后台之后的 UI 线程上调用计算完成。 后台计算的结果为作为参数传递给此步骤。
按照文档,您可以在主活动中启动异步任务。在 onPreExecute 方法中,可以显示初始屏幕。
在doInBackGround方法中,插入执行所有加载操作的代码。如果要为用户提供有关加载状态的一些信息,可以在此方法中使用 publishProgress 来发布一个或多个进度单元。这些值发布在 UI 线程的 onProgressUpdate(Progress...) 步骤中。
最后,在onPostExecute方法中,您可以删除初始屏幕并运行游戏的加载屏幕。
另请查看此示例。
冗长的回答,请耐心等待。
你必须做一些事情才能得到你想要的东西。
首先分离您的活动,而不是多次调用 setContentView。
然后设置一个域对象,作为您的"游戏设置",以便您可以加载它,初始化它的所有字段。
还有一个配置对象来加载您的设置。
在下面的示例中,我没有加载您的所有字段,但我希望您明白这一点。
最终结果是这样的:
第一次活动:
package com.blundell.tut.ui;
import com.blundell.tut.R;
import com.blundell.tut.domain.Config;
import com.blundell.tut.task.LoadingTask;
import com.blundell.tut.task.LoadingTask.LoadingTaskFinishedListener;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.ProgressBar;
public class SplashActivity extends Activity implements LoadingTaskFinishedListener {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Show the splash screen
setContentView(R.layout.activity_splash);
// Find the progress bar
ProgressBar progressBar = (ProgressBar) findViewById(R.id.activity_splash_progress_bar);
// Start your loading
new LoadingTask(progressBar, this, getAssets(), new Config()).execute("www.google.co.uk"); // Pass in whatever you need a url is just an example we don't use it in this tutorial
}
// This is the callback for when your async task has finished
@Override
public void onTaskFinished(GameDomain result) {
// The result object is your loaded files!
completeSplash();
}
private void completeSplash(){
startApp();
finish(); // Don't forget to finish this Splash Activity so the user can't return to it!
}
private void startApp() {
Intent intent = new Intent(SplashActivity.this, MainActivity.class);
startActivity(intent);
}
}
然后执行加载的 ASyncTask :
package com.blundell.tut.task;
import com.blundell.tut.domain.Config;
import com.blundell.tut.domain.GameDomain;
import android.content.res.AssetManager;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.ProgressBar;
public class LoadingTask extends AsyncTask<String, Integer, GameDomain> {
public interface LoadingTaskFinishedListener {
void onTaskFinished(GameDomain domain); // If you want to pass something back to the listener add a param to this method
}
private static final int NUM_OF_TASKS = 2;
// This is the progress bar you want to update while the task is in progress
private final ProgressBar progressBar;
// This is the listener that will be told when this task is finished
private final LoadingTaskFinishedListener finishedListener;
private final AssetManager assets;
private final Config config;
/**
* A Loading task that will load some resources that are necessary for the app to start
* @param progressBar - the progress bar you want to update while the task is in progress
* @param finishedListener - the listener that will be told when this task is finished
*/
public LoadingTask(ProgressBar progressBar, LoadingTaskFinishedListener finishedListener, AssetManager assets, Config config) {
this.progressBar = progressBar;
this.finishedListener = finishedListener;
this.assets = assets;
this.config = config;
}
@Override
protected GameDomain doInBackground(String... params) {
GameDomain gameDomain = new GameDomain();
Log.i("Tutorial", "Starting task with url: "+params[0]);
if(resourcesDontAlreadyExist()){
downloadResources(gameDomain);
}
return gameDomain;
}
private boolean resourcesDontAlreadyExist() {
// Here you would query your app's internal state to see if this download had been performed before
// Perhaps once checked save this in a shared preference for speed of access next time
return true; // returning true so we show the splash every time
}
private void downloadResources(GameDomain gameDomain) {
// We are just imitating some process thats takes a bit of time (loading of resources / downloading)
int count = NUM_OF_TASKS;
// Do some long loading things
// Setup all the Game Engine components
gameDomain.setGameEngineLog("WSGameEngine", config.LOG_TYPE);
updateProgress(count--);
gameDomain.setAssets(assets);
updateProgress(count--);
}
public void updateProgress(int count) {
// Update the progress bar after every step
int progress = (int) ((NUM_OF_TASKS / (float) count) * 100);
publishProgress(progress);
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
progressBar.setProgress(values[0]); // This is ran on the UI thread so it is ok to update our progress bar ( a UI view ) here
}
@Override
protected void onPostExecute(GameDomain result) {
super.onPostExecute(result);
finishedListener.onTaskFinished(result); // Tell whoever was listening we have finished
}
}
然后是你正在实例化的对象:
public class GameDomain {
private WSLog gameEngineLog;
private FileIO io;
public void setGameEngineLog(String name, String logType){
gameEngineLog = new WSLog(name);
gameEngineLog.setLogType(logType);
}
public void setAssets(AssetManager assets) {
io = new FileIO(assets);
}
}
以及您的配置:
package com.blundell.tut.domain;
public class Config {
public String LOG_TYPE = "logType";
}
最后,您的唤醒锁应该在每个活动中"得到"创建并在"暂停"中释放