Android 具有网络负载和最短启动显示时间的启动画面

Android Splash Screen with network load and minimum splash display time

我目前在启动画面活动中使用以下结构,以便在指定时间段内显示它:

    new Handler().postDelayed(new Runnable() {
       @Override
       public void run() {
            startMainActivity();
       }
    }, SPLASH_DISPLAY_LENGHT);

然而,我只是创建一个应用程序,它使用 AsyncTask 从网络加载一些信息到它的初始屏幕上,如下所示:

startUpAsyncTask = new StartUpAsyncTask(this);
startUpAsyncTask.execute();

现在我想这样实现处理程序:

  1. 如果在网络加载期间出现故障,它会停止处理程序以移至 MainActivity。
  2. 如果网络加载持续时间超过 SPLASH_DISPLAY_LENGHT activity 等到网络加载在 StartUpAsyncTask 完成,然后转到下一个 activity。
  3. 如果网络 StartUpAsyncTask 很快结束,启动画面至少显示 SPLASH_DISPLAY_LENGHT 时间长度。

我的问题是如何同步这个AsyncTask和Handler来实现这样的约束。

您可以在启动画面中注册一个 BroadcastReceiver 并注册一个 LocalBroadcastManager,它将收到来自您的 AsyncTask 的成功消息并设置一个标志。另一个 BroadcastReceiver 将在您的处理程序中注册,以防在 SPLASH_DISPLAY_LENGHT 已经过去时尚未设置标志,并且将在 startMainActivity() 从您的 AsyncTask 收到广播时注册;否则,如果在您的处理程序中完成 SPLASH_DISPLAY_LENGHT 时已经设置了标志,它将直接 startMainActivity().

在你的SplashActivity中:

private class SplashActivity extends Activity {
    public static final String ACTION_DATA_LOADING_COMPLETE = "com.example.myapp.ACTION_DATA_LOADING_COMPLETE";

    private LocalBroadcastManager localBroadcastManager;

    private boolean dataLoadingComplete = false;

    @Override
    private void onCreate(Bundle savedInstanceState) {
        ...

        localBroadcastManager = LocalBroadcastManager.getInstance(this);

        localBroadcastManager .registerBroadcastReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                dataLoadingComplete = true;
            }
        }, new IntentFilter(ACTION_DATA_LOADING_COMPLETE));

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                localBroadcastManager.registerBroadcastReceiver(new BroadcastReceiver() {
                    @Override
                    public void onReceive(Context context, Intent intent) {
                        startMainActivity();
                    }
                }, new IntentFilter(ACTION_DATA_LOADING_COMPLETE));

                if (dataLoadingComplete)
                    localBroadcastManager.sendBroadcast(new Intent(ACTION_DATA_LOADING_COMPLETE));
            }
        }, SPLASH_DISPLAY_LENGHT);
    }
}

在你的 AsyncTask:

@Override
onPostExecute(...) {
    super.onPostExecute(...)

    ...

    LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent(SplashActivity.ACTION_DATA_LOADING_COMPLETE));
}
package com.example;

import java.util.Timer;
import java.util.TimerTask;

import android.app.Activity;
import android.os.AsyncTask;

public class SplashActivity extends Activity{

    private Timer timer;
    private boolean isTaskRunning = false;
    private boolean isTimerFinished = false;
    private long SPLASH_DURATION = 2*1000;

    protected void onCreate(android.os.Bundle savedInstanceState) {
        setContentView(R.layout.badgeview);

        new MyTask().execute();

        timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                isTimerFinished = true;
               if(!isTaskRunning){
                   //startNextActivity;
               }

            }
        }, SPLASH_DURATION);

    }

    class MyTask extends AsyncTask<Void, Void, Void>{
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            isTaskRunning = true;
        }
        @Override
        protected Void doInBackground(Void... params) {
            //do whatever you require from network
            return null;
        }
        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
            isTaskRunning = false;
            if(!isTimerFinished){
                timer.cancel();
            }
            //startNextActivity
        }
    }
}

像这样在处理程序中放置条件

new Handler().postDelayed(new Runnable() {
       @Override
       public void run() {
            if(isTaskSuccessfull)
            startMainActivity();
            else
                isHandlerTimeout = true;
       }
    },

在 Asyn 的 OnPost() 方法中,当任务成功完成时,首先将 asyn 任务的 flag(isTaskSuccessfull) 的值更改为 true,然后检查 isHandlerTimeout 是否为真,如果是,则从 asyn 的 onPost() 调用方法 startMainActivity()。

private static final long SPLASH_DURATION = 2*1000;
private long mStartTimestamp;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.your_layout);

    mStartTimestamp = System.currentTimeMillis();
    new MyTask().execute();
}

class MyTask extends AsyncTask<Void, Void, Boolean>{

    @Override
    protected Boolean doInBackground(Void... params) {
        // your logic here
        return true;
    }

    @Override
    protected void onPostExecute(Boolean success) {
        super.onPostExecute(success);
        // check your result here
        if(success){
            long timeStop = System.currentTimeMillis();
            long delta = timeStop - mStartTimestamp;
            if (delta >= SPLASH_DURATION) {
                startMainActivity();
            } else {
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        startMainActivity();
                    }
                }, SPLASH_DURATION - delta);
            }
        } else {
            // handle the error
        }
    }
}