按顺序运行AsyncTasks并共享相同的布局

时间:2013-12-21 21:32:01

标签: android android-layout android-asynctask

我目前正在开展一个项目SplashScreen,需要启动AsyncTask#1,然后AsyncTask#2启用AsyncTask#5。完成所有操作后,应将用户带到HomeActivity

AsyncTask#1加载所有其他任务所需的数据。此外,我需要AsyncTask#2AsyncTask#5来共享相同的布局(ImageView + TextView)。

基本上,就像加载屏幕一样:TextView: "Loading items"ImageView: item currently being loaded。即使图像将快速滚动,我仍然必须让用户看到图像加载/更改。

我正在手动编写以下内容,因此请忽略语法错误(如果有):/


目前,我的splashScreen看起来像这样:

try {
    DatabaseSetup async1 = new DatabaseSetup(this);
    async1.execute().get;
    new Async2.execute();
    new Async3.execute();
    new Async4.execute();
    new Async5.execute();
} finally {
    Intent i = new Intent(this, HomePage.class);
    StartActivity(i);
}


Async2 to 5

class Async# extends AsyncTask<Void, String, Boolean> {
    private Context context;
    private Activity activity;
    private TextView tv;
    private ImageView iv;

    public Async#(Context context) {
        this.context = context;
        this.activity = (Activity) context;
    }

    onPreExecute() {
        super.onPreExecute();
        tv = (TextView) activity.findViewById(R.id.tvLoader);
        iv = (ImageView) activity.findViewById(R.id.ivLoader);
    }

    doInBackground() {
        publishProgress("Running Async#");
        .
        .
        .
        for(int i=0; i < items.length; i++) {
            publishProgress(item[i].getImageLink());
        }
    }

    onProgress(String... values) {
        if(values[0].contains("Loading")
            tvLoader.setText(values[0]);
        else()
            ivLoader.setImageURL(values[0]);
    }
}

那么,这样做的正确方法是什么?我在某处读到如果我使用async1.execute().get(),只有在Async1完成后才会调用以下行。我完全糊涂了。此代码有效,但有时会得到Surface#2 is not valid.

我不确定我是否要使用inflater? ImageView实际上是一个我从Loopj(SmartImageView)获取的库来缓存我得到的图像。

logcat的:

12-21 16:45:16.722: E/ViewSystem(8941): ViewRootImpl #2 Surface is not valid.
12-21 16:45:16.772: D/AbsListView(8941): Get MotionRecognitionManager
12-21 16:45:16.782: D/AbsListView(8941): onVisibilityChanged() is called, visibility : 4
12-21 16:45:16.782: D/AbsListView(8941): unregisterIRListener() is called 
12-21 16:45:16.782: D/AbsListView(8941): onVisibilityChanged() is called, visibility : 0
12-21 16:45:16.782: D/AbsListView(8941): unregisterIRListener() is called 
12-21 16:45:16.852: D/libEGL(8941): loaded /system/lib/egl/libEGL_adreno200.so
12-21 16:45:16.852: D/libEGL(8941): loaded /system/lib/egl/libGLESv1_CM_adreno200.so
12-21 16:45:16.862: D/libEGL(8941): loaded /system/lib/egl/libGLESv2_adreno200.so
12-21 16:45:16.862: I/Adreno200-EGL(8941): <qeglDrvAPI_eglInitialize:265>: EGL 1.4 QUALCOMM build: HAREESHG_Nondeterministic_AU+PATCH[ES]_msm8960_JB_1.9.6_MR2_CL3219408_release_ENGG (CL3219408)
12-21 16:45:16.862: I/Adreno200-EGL(8941): Build Date: 09/28/13 Sat
12-21 16:45:16.862: I/Adreno200-EGL(8941): Local Branch: hhh
12-21 16:45:16.862: I/Adreno200-EGL(8941): Remote Branch: quic/jb_1.9.6_1
12-21 16:45:16.862: I/Adreno200-EGL(8941): Local Patches: 8d50ec23e42ef52b570aa6ff1650afac0b503d78 CL3219408: Fix in the Glreadpixels for negative offsets and larger dimensions.
12-21 16:45:16.862: I/Adreno200-EGL(8941):                  801859126f6ca69482b39a34ca61447e3f7cded8 rb: fix panel settings to clear undrawn/undefined buffers
12-21 16:45:16.862: I/Adreno200-EGL(8941): Reconstruct Branch: LOCAL_PATCH[ES]
12-21 16:45:16.902: D/OpenGLRenderer(8941): Enabling debug mode 0
12-21 16:45:16.932: D/AbsListView(8941): unregisterIRListener() is called 
12-21 16:45:16.952: D/AbsListView(8941): unregisterIRListener() is called 
12-21 16:45:17.022: D/AbsListView(8941): unregisterIRListener() is called 
12-21 16:45:17.052: D/AbsListView(8941): unregisterIRListener() is called 

非常感谢您阅读所有这些内容!

1 个答案:

答案 0 :(得分:1)

您可以使用简单的信号量方法。 让你的Splash活动实现一个简单的界面:

public interface DecrementCallback{
    public void setCount(int cnt);
    public void onDecrementCount();
}

将成员定义为计数器:

private int cnt = 0;

您要实施的方法应该是:

        @Override
        public void setCount(int cnt) {
            this.cnt = cnt;
        }

        @Override
        public void onDecrementCount() {
            cnt--;
            if(cnt <= 0){
                /**
                 * Start your main activity
                 */
            }
        }

在启动asyntasks之前,设置计数器值:

setCount(5);

将此方法添加到您的asynctasks:

@Override
protected void onPostExecute(Void result) {
    super.onPostExecute(result);
    ((DecrementCallback)activity).onDecrementCount();
}

当您在所有异步通信中共享相同的TextView和ImageView时,您应该非常了解自己所做的事情,因为如果您没有正确更新,可能会让用户感到困惑。

修改

如果要按顺序运行asynctasks(首先是Async1,然后是Asyn2,然后是Async3),可以将onPostExecute()方法修改为:

    @Override
protected void onPostExecute(Void result) {
    super.onPostExecute(result);
    ((DecrementCallback)activity).onDecrementCount();

            if(this instanceof Async1){
            new Async2(activity).execute();
    }else if(this instanceof Async2){
        new Async3(activity).execute();
    }else if(this instanceof Async3){
        new Async4(activity).execute();
    }else if(this instanceof Async4){
        new Async5(activity).execute();
    }
}

然后,您只需要在活动中启动Async1。

编辑2:

如果要从Splash活动启动所有异步任务,可以将回调修改为:

public static interface DecrementCallback{
    public void setCount(int cnt);
    public void onDecrementCount(AsyncTask<Void, Void, Void> task);
}

asynctask方法应该是:

@Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);

        ((DecrementCallback)activity).onDecrementCount(this);
    }

您活动中的覆盖方法应如下所示:

@Override
        public void onDecrementCount(AsyncTask<Void, Void, Void> task) {
            cnt--;
            if(cnt <= 0){
                /**
                 * Start your main activity
                 */
            }

            if(task instanceof Async1){
                new Async2(activity).execute();
            }else if(task instanceof Async2){
                new Async3(activity).execute();
            }else if(task instanceof Async3){
                new Async4(activity).execute();
            }else if(task instanceof Async4){
                new Async5(activity).execute();
            }
        }

你暴露了很多变种。希望它们有用。

问候。