내 주요 활동 사용자가 앱을 나가거나 다른 활동을 변경할 때마다 자동 저장하려고합니다. 그래서 잘 작동하는 활동의 OnPause 메서드에서 저장 함수를 구현했습니다. 문제는 저장 프로세스에 몇 초가 걸릴 수 있으므로 진행되는 동안 진행 대화 상자를 원했습니다. 그래서 나는 ASyncTask를 다음과 같이 implenmet했다.AsyncTask가 여전히 UI 스레드를 차단하고 있습니다.
@Override
public void onPause()
{
super.onPause();
// save sheet when user is leaving activity
SaveTask task = new SaveTask(PlayCharacterActivity.this);
task.execute();
}
private class SaveTask extends AsyncTask <Void, Void, Void> {
private ProgressDialog dialog;
public SaveTask(PlayCharacterActivity activity) {
}
@Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(PlayCharacterActivity.this);
dialog.setMessage("Saving...");
dialog.show();
dialog.setIndeterminate(true);
dialog.setCancelable(false);
}
@Override
protected void onPostExecute(Void result) {
if (dialog.isShowing()) {
dialog.dismiss();
}
super.onPostExecute(result);
}
@Override
protected Void doInBackground(Void... params) {
try {
//Log.d("plch:OnPause", "starting save");
Sheet.getInstance().Save();
//Log.d("plch:OnPause", "finished save");
} catch (RuntimeException e) {
e.printStackTrace();
}
return null;
}
}
문제는 대화 상자가 백그라운드 작업이 완료 될 때까지 나타나지 않는다는 것이다. 그리고 logcat에서 주 스레드가 여전히 차단되고 있음을 알 수 있습니다. 나는 그것이 직렬화를 할 때 저장 함수의 중간에서 일어난다 고 생각한다.
저장은 다음과 같이이다 :
public void Save()
{
long dtMili = System.currentTimeMillis();
Date d = new Date(dtMili);
CharSequence s = DateFormat.format("hh:mm:ss", d.getTime());
// use this flag to know whether to back up the saved file or not
boolean saveSuccessful = false;
//_xml = new String("");
dtMili = System.currentTimeMillis();
d = new Date(dtMili);
Log.d("Load/Save", "started serialising: " + DateFormat.format("hh:mm:ss", d.getTime()));
_xml = _instance.Serialise();
dtMili = System.currentTimeMillis();
d = new Date(dtMili);
Log.d("Load/Save", "finished serialising: " + DateFormat.format("hh:mm:ss", d.getTime()));
try
{
//---SD Card Storage---
File sdCard = Environment.getExternalStorageDirectory();
File directory = new File (sdCard.getAbsolutePath() + "/RPGenius");
directory.mkdirs();
File file = new File(directory, _name + ".rpg");
FileOutputStream fOut = new FileOutputStream(file);
Log.d("Saving to: ", file.getAbsolutePath());
//---write the string to the file---
OutputStreamWriter osw = new OutputStreamWriter(fOut);
//DebugHelper.DebugMessage("File contents: " + _xml);
dtMili = System.currentTimeMillis();
d = new Date(dtMili);
Log.d("Load/Save", "started writing file: " + DateFormat.format("hh:mm:ss", d.getTime()));
osw.write(_xml);
osw.flush();
osw.close();
dtMili = System.currentTimeMillis();
d = new Date(dtMili);
Log.d("Load/Save", "finished writing file: " + DateFormat.format("hh:mm:ss", d.getTime()));
saveSuccessful = true;
}
catch (NullPointerException npe)
{
npe.printStackTrace();
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
// if the save was completely successfully, back it up
if (saveSuccessful)
{
File sdCard = Environment.getExternalStorageDirectory();
File directory = new File (sdCard.getAbsolutePath() + "/RPGenius");
File file = new File(directory, _name + ".rpg");
if (file.exists())
{
// locate backup directory and create if not present
File backupDirectory = new File (sdCard.getAbsolutePath() + "/RPGenius/Backups");
backupDirectory.mkdirs();
// create target file location/name
File backupFile = new File(backupDirectory, _name + ".rpg");
// attempt to copy file
try {
FileInputStream inStream = new FileInputStream(file);
FileOutputStream outStream = new FileOutputStream(backupFile);
FileChannel inChannel = inStream.getChannel();
FileChannel outChannel = outStream.getChannel();
inChannel.transferTo(0, inChannel.size(), outChannel);
inStream.close();
outStream.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
직렬화를이 같다 :
@Override
public String Serialise() {
// produce xml string to represent this object
_indents = 0;
_xml = new String("");
StartXmlItem("Sheet");
//AddSimpleXmlItem("Name", _name);
StartXmlItem("Stats");
for (XmlSerialisable stat: _stats)
{
AddComplexXmlItem(stat);
}
EndXmlItem("Stats");
StartXmlItem("Effects");
for (XmlSerialisable effect: _effects)
{
AddComplexXmlItem(effect);
}
EndXmlItem("Effects");
StartXmlItem("Pages");
for (XmlSerialisable page: _pages)
{
AddComplexXmlItem(page);
}
EndXmlItem("Pages");
EndXmlItem("Sheet");
return _xml;
}
그들이해서 ProgressDialog 문제에 해당하지 않는 한 난에는 직렬화/저장 방법 개선에 즉시 관심 없어 . 누구든지 도와 줄 수 있습니까? 단지 할)
private ProgressDialog dialog; //should be declared as field in Activity
public SaveTask(PlayCharacterActivity activity) { //don't pass the activity to AsyncTask
}
을 그런 다음 onPreExecute에서 (: 다음 AsyncTask
에서 진행 막대 필드와 쓸모없는 생성자를 제거 모든
첫째 :
'dialog.show();'를'onPreExecute'의 마지막 줄에 놓고 (대화 상자를 모두 사용한 후에) 다시 테스트하십시오. –
"그리고 메인 스레드가 여전히 차단되고 있음을 logcat에서 볼 수 있습니다."- 이것이 가능한 방법을 알지 못합니다. 문제의 LogCat 항목을 제공하고 분석을 설명해 주시겠습니까? 그 외에도, 대화 형 - 일시 중지 방식의 접근 방식이 올바르게 작동하고 처음에는 좋은 생각이라고 생각하는 이유는 무엇입니까? – CommonsWare