如何使用 AsyncTask 实现初始化



我想用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";
}

最后,您的唤醒锁应该在每个活动中"得到"创建并在"暂停"中释放

最新更新