ProgressDialog VS 오리엔테이션 변경이있는 Asynctask
-
10-12-2019 - |
문제
필사적 인 날짜가 아마도 마침내 거의 작업 예제를 만들었습니다.
목표 : 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;
}
}
}
}
해결책
Yesterday, I wrote a blog post which describes handling configuration changes using retained Fragment
s.
The TL;DR is to use host your AsyncTask
inside a Fragment
, call setRetainInstance(true)
on the Fragment
, and report the AsyncTask
's progress/results back to it's Activity
through the retained Fragment
.
다른 팁
add this to Test activity in manifest
android:configChanges="orientation|keyboardHidden"></activity>
and put this in your test class
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
Put android:screenOrientation="portrait"
in your <activity />
tag of manifest file.
After doing that, put these lines in protected void onPreExecute()
method of asyncTask:
dialog.setMessage("Please wait.....");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();