4

經過幾天絕望的日子,我終於創建了幾乎可行的例子。AsyncTask with ProgressDialog vs orientation orientation

onCreate中的目標:我想在AsyncTask中下載和解析XML文件,顯示進度對話框,更新UI並關閉對話框。

問題:當方向更改時重新啓動活動並且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; 
     } 
    } 
} 

} 
+0

看[這裏](http://www.codeproject.com/Articles/162201/Painless-AsyncTask-and-ProgressDialog-Usage)。你可以在那裏找到你的問題的答案。這是一個非常優雅的解決方案。 – Yury 2012-07-05 08:28:59

+0

查看我關於此主題的帖子:[**使用'Fragment's **處理配置更改](http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html) – 2013-04-30 16:47:24

回答

5

昨天,我寫了一個blog post其描述處理使用保存Fragment的配置變化。

的TL; DR是使用託管AsyncTaskFragment,在FragmentsetRetainInstance(true)AsyncTask的進步/結果報告給它的Activity通過保留Fragment

+0

看起來很有希望。我現在沒有時間學習更多,但看起來非常好。不過,我的平臺目標是2.2+,所以現在暫時停止使用。我稍後再看看我的下一個應用程序/版本。謝謝您的時間 – 2013-05-06 12:46:22

+0

@JanPfeifer您也可以使用[支持庫](http://developer.android.com/tools/extras/support-library.html)......這將確保在運行Android的設備上一切正常1.6及以上。 – 2013-05-06 21:41:54

+0

好吧,現在它真的值得一試。我不知道支持lib。 Thx再次。 – 2013-05-07 08:56:20

2

內容添加到清單中

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

測試活動,並把這個在您的測試類

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

試試這個,讓我知道如果這個工作.. =] – 5hssba 2012-03-09 08:43:33

+1

感謝您的快速響應。但這不是我真正需要的。這隻會阻止活動重新啓動。谷歌不鼓勵它。如果我使用它並手動殺死我的應用程序(例如Advanced TaskKiller)。那麼結果是一樣的。對話框彈出,沒有別的。 – 2012-03-09 08:52:48

0

android:screenOrientation="portrait"<activity />標籤清單文件。 這樣做後,把這些線的AsyncTask的保護無效onPreExecute()方法:

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

感謝您的回覆。這也不會工作。我不想將我的活動修復爲縱向。將dialog.show()移動到onPreExecute也不起作用。 – 2012-03-09 10:56:18

相關問題