4

필사적으로 몇 일 지나서 마침내 거의 실제 예제를 만들었습니다.AsyncTask ProgressDialog 대 오리 엔테이션 변경

목표 : onCreate AsyncTask에서 다운로드 및 parseXML 파일을 다운로드하고 진행률 대화 상자를 표시하고 UI를 업데이트하고 대화 상자를 닫으 려합니다.

문제 : 오리엔테이션이 변경되면 작업이 다시 시작되고 AsyncTask가 참조를 잃습니다. 그것에 대해 많은 질문과 블로그가 있습니다. 하지만이 특정 솔루션이 왜 작동하지 않는지 알 수는 없습니다. 또는이 경우 안드로이드가 대화 상자를 처리하는 방법.

상태 : 앱을 시작할 때 모든 것이 정상입니다. 장치를 회전시킬 수 있으며 수동으로 메뉴를 통해 작업을 다시 시작할 수 있습니다. 하지만 작업이 끝난 후 오리엔테이션을 다시 변경하면 대화 상자가 (예상대로) 튀어 나오면 아무 일도 일어나지 않습니다. 진행 상태가 변경되지 않고 대화 상자가 닫히지 않습니다. 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

+0

이 주제에 대한 내 게시물을 확인하십시오 : [** Fragment's **로 구성 변경 처리 (http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html) –

답변

5

어제, 나는 Fragment의 유지 사용하여 구성 변경 사항을 처리 설명하는 blog post을 썼다.

는 TL; DR, 당신의 AsyncTaskFragment 돌며 호스트 사용 FragmentsetRetainInstance(true)을 호출하고는 유지 Fragment 통해 Activity의에 다시 AsyncTask의 진행/결과를보고하는 것입니다.

+0

유망 해 보인다. 나는 지금 더 많은 것을 공부할 시간이 없다. 그러나 그것은 정말로 좋게 보인다. 그러나 내 플랫폼 타겟은 2.2+이므로 현재는 사용하지 않습니다. 나는 나의 다음 apps/버전을 위해 이것을 나중에 본다. 시간 내 주셔서 감사합니다. –

+0

@JanPfeifer Android를 실행하는 기기에서 모든 것이 작동하도록 [support library] (http://developer.android.com/tools/extras/support-library.html)도 사용할 수 있습니다. 1.6 이상. –

+0

글쎄, 지금은 정말 가치가있어. lib 지원에 대해서는 전혀 몰랐습니다. 다시 Thx. –

2

이 매니페스트

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

의 활동을 테스트하기 위해 추가

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

이걸 시도해보고 알려 주시면 .. =] – 5hssba

+1

감사합니다. 그러나 이것은 내가 실제로 필요한 것이 아닙니다. 이것은 활동 재시작 만 방지합니다. 그리고 구글은 그것을 낙담시킨다. 내가 그것을 사용하고 수동으로 응용 프로그램을 죽일 경우 (예를 들어 Advanced TaskKiller). 그러면 결과는 같습니다. 대화 상자가 튀어 나오고 다른 것은 나오지 않습니다. –

0

<activity /> 태그에 android:screenOrientation="portrait"을 넣어 테스트 클래스에 넣고 매니페스트 파일의 가 그 일을 한 후, AsyncTask를의 보호 무효 onPreExecute() 방법이 라인을 넣어 :

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

답장을 보내 주셔서 감사합니다. 이것 역시 효과가 없습니다. 내 액티비티를 세로 방향으로 고정하고 싶지 않습니다. onPreExecute로 dialog.show()를 움직이는 것도 효과가 없었습니다. –