필사적으로 몇 일 지나서 마침내 거의 실제 예제를 만들었습니다.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;
}
}
}
}
[여기] (http://www.codeproject.com/Articles/162201/Painless-AsyncTask-and-ProgressDialog-Usage)를보십시오. 거기서 당신의 질문에 대한 답을 찾을 수 있습니다. 매우 우아한 솔루션입니다. – Yury
이 주제에 대한 내 게시물을 확인하십시오 : [** Fragment's **로 구성 변경 처리 (http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html) –