我的主要活动我想在用户离开应用程序或更改其他活动时自动保存。所以我在activity的OnPause方法中实现了save函数,该方法工作正常。问题是保存过程可能需要几秒钟,所以我想要一个progressdialog,当它发生时。所以我用这样的ASyncTask实现了这个:
@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();
}
}
}
}
Serialise是这样的:
@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;
}
我不会立即对save / serialise方法的改进感兴趣,除非它们与progressdialog问题相关。有人可以帮忙吗?
答案 0 :(得分:1)
我建议您对AsyncTask
进行以下更改:
首先从AsyncTask
:
private ProgressDialog dialog; //should be declared as field in Activity
public SaveTask(PlayCharacterActivity activity) { //don't pass the activity to AsyncTask
}
然后在onPreExecute()中执行:
@Override
protected void onPreExecute() {
showDialog(); //call a method in your Activity that shows your dialog as you want
}
请记住,AsyncTask的onPreExecute方法在UI线程中运行,因此您可以在此处理Activity中的视图。请参阅文档:http://developer.android.com/reference/android/os/AsyncTask.html#onPreExecute()
答案 1 :(得分:0)
尝试将对话框移动到外部类并在AsyncTask外部以静态方法
打开它dialog = ProgressDialog.show(...)
之前
task.execute();
应该可以从onPostExecute
关闭它