android – AsyncTask与ProgressDialog vs方向更改

经过几个绝望的日子,我终于创造了几乎成功的榜样.

目标:在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;
        }
    }
}

}

解决方法:

昨天,我写了一个blog post,它描述了使用保留的片段处理配置更改.

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

上一篇:android – 如何禁用/启用进度对话框按钮


下一篇:Python股票分析系列——基础股票数据操作(一).p3