【问题标题】:AsyncTask with ProgressDialog vs orientation change带有 ProgressDialog 的 AsyncTask 与方向更改
【发布时间】:2012-03-09 08:29:45
【问题描述】:

经过几天的绝望,我终于创建了几乎可以工作的例子。

目标:在 onCreate 我想在 AsyncTask 中下载和解析 XML 文件,显示进度对话框,更新 UI 并关闭对话框。

问题: 当方向改变时,Activity 重新启动并且 AsyncTask 失去对它的引用。有很多关于它的问题和博客。但我不知道为什么这个特定的解决方案不起作用。或者在这种情况下android如何处理对话框。

状态:当我启动一个应用程序时一切正常。我可以旋转设备,我可以通过菜单再次手动启动任务。但是在任务完成后,我再次更改方向弹出对话框(如预期的那样)并且没有其他任何事情发生。没有进度变化,没有对话框关闭。 AsyncTask 正常结束。

代码:

package com.test;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;

public class Test extends TabActivity {
DownloadFileAsync task;
ProgressDialog   progressDialog;
static final int PROGRESS_DIALOG = 0;

private static Data      data;


/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {       
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    /* - Run from different locations bug - */
    //http://code.google.com/p/android/issues/detail?id=2373
    if (!isTaskRoot()) {
        final Intent intent = getIntent();
        final String intentAction = intent.getAction();
        if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) &&
                intentAction != null && intentAction.equals(Intent.ACTION_MAIN)) {
            finish();
        }
    }
    /* - /Run from different locations bug  */

    /* -------------- Tabs ---------------- */
    Resources res = getResources();
    TabHost mTabHost = getTabHost();
    mTabHost.addTab(mTabHost.newTabSpec("overview").setIndicator("MYTAB1",res.getDrawable(R.drawable.ic_tab_home)).setContent(R.id.tab1));      
    mTabHost.setCurrentTab(0);
    /* -------------- /Tabs --------------- */

    /* -------------- /Data --------------- */
    task = (DownloadFileAsync)getLastNonConfigurationInstance();
    if(task!= null) {
        task.setActivity(this);
    } else {
        if(data == null) {
            File datafile = this.getFileStreamPath("data.dat");
            if(datafile.exists()){
                //Log.d("log", "File exists!");
                try {
                    long time = System.currentTimeMillis();
                    ObjectInputStream obj = new ObjectInputStream(new FileInputStream(datafile));
                    data = (Data)obj.readObject();
                    obj.close();
                    Log.d("time", "loaded in:"+(System.currentTimeMillis()- time));

                    if(data.isUpToDate() || !isOnline()){
                        update();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    datafile.delete();
                    data = null;
                }
                //Log.d("log", "Passed?");
            }
        }       
        /* DEBUG if(data == null || !data.isUpToDate())*/ this.synchronize(); 
    }
    /* -------------- /Data --------------- */

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    menu.add("Synchronize").setIcon(R.drawable.ic_menu_refresh);     
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    synchronize();
    return super.onOptionsItemSelected(item);
}

@Override
public Object onRetainNonConfigurationInstance() {
    if(task != null) task.setActivity(null);      
    return(task);
}

protected Dialog onCreateDialog(int id) {
    switch (id) {
    case PROGRESS_DIALOG:
        progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("Aktualizuji ...");
        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        progressDialog.setCancelable(false);            
        //progressDialog.show();            
        return progressDialog;
    default:
        return null;
    }
}

public void update() {

}

private void onTaskCompleted() {
    task = null;        
    dismissDialog(PROGRESS_DIALOG);     
    Log.d("tok","Task.onComplete");
    update();       
}

public void synchronize(){
    if(isOnline()) {
        showDialog(PROGRESS_DIALOG);
        progressDialog.setProgress(0); // <-- this is the last time progressDialog updates
        task = new DownloadFileAsync(this);
        task.execute();
    }
}

public boolean isOnline() {
    ConnectivityManager cm =
        (ConnectivityManager) getSystemService(WaspActivity.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    if (netInfo != null && netInfo.isConnectedOrConnecting()) {
        return true;
    }
    return false;
}

private static class DownloadFileAsync extends AsyncTask<String, String, String> {
    private Data tempData;
    private Test activity;
    private int progress = 0;
    private File metafile;
    private File tempDir;
    private FileOutputStream fos;

    public DownloadFileAsync(Test activity) {
        this.setActivity(activity);


        ... some more init ...
    }

    public void setActivity(Test activity) {
        this.activity = activity;           
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        tempData = new Data();
    }

    @Override
    protected String doInBackground(String... aurl) {
        try {

        ... some heavy load  ...
        //this.progress = someValue;                

        } catch (Exception e) {
            Log.d("Error", "Error while processing files. Code:"+e.getMessage());
            e.printStackTrace();
        }

        //Log.d("time","Task "+(System.currentTimeMillis() - time));
        return null;

    }
    protected void onProgressUpdate(String... progress) {            
        if(activity != null) activity.progressDialog.setProgress(this.progress);
    }

    @Override
    protected void onPostExecute(String unused) {
        data = tempData;
        tempData = null;
        if(activity != null) {
            activity.onTaskCompleted();
            activity = null;
        }
    }
}

}

【问题讨论】:

标签: android android-asynctask progressdialog android-orientation


【解决方案1】:

昨天,我写了一篇blog post,描述了使用保留的Fragments 处理配置更改。

TL;DR 是在Fragment 中使用您的AsyncTask,在Fragment 上调用setRetainInstance(true),并通过AsyncTask 将进度/结果报告给Activity保留Fragment

【讨论】:

  • 看起来很有希望。我现在没有时间学习更多,但看起来真的很好。但是我的平台目标是 2.2+,所以它现在不可用。我稍后会考虑下一个应用程序/版本。感谢您的宝贵时间
  • @JanPfeifer 您也可以使用support library...这将确保一切都在运行 Android 1.6 及更高版本的设备上运行。
  • 嗯,现在真的值得一试。我不知道支持库。再次感谢。
【解决方案2】:

将此添加到清单中的测试活动

android:configChanges="orientation|keyboardHidden"></activity>

把它放到你的测试类中

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
}

【讨论】:

  • 感谢您的快速响应。但这不是我真正需要的。这只防止活动重新启动。谷歌不鼓励这样做。如果我使用它并手动终止我的应用程序(例如 Advanced TaskKiller)。然后结果是一样的。对话框弹出,没有其他内容。
【解决方案3】:

android:screenOrientation="portrait" 放入清单文件的&lt;activity /&gt; 标记中。 完成后,将这些行放入 asyncTask 的 protected void onPreExecute() 方法中:

dialog.setMessage("Please wait.....");
            dialog.setIndeterminate(true);
            dialog.setCancelable(false);
            dialog.show();

【讨论】:

  • 感谢您的回复。这也行不通。我不想将我的活动修复为纵向。将 dialog.show() 移动到 onPreExecute 也不起作用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-15
相关资源
最近更新 更多