2014-03-02 2 views
0

내 주요 활동 사용자가 앱을 나가거나 다른 활동을 변경할 때마다 자동 저장하려고합니다. 그래서 잘 작동하는 활동의 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에서 진행 막대 필드와 쓸모없는 생성자를 제거 모든

첫째 :

+0

'dialog.show();'를'onPreExecute'의 마지막 줄에 놓고 (대화 상자를 모두 사용한 후에) 다시 테스트하십시오. –

+2

"그리고 메인 스레드가 여전히 차단되고 있음을 logcat에서 볼 수 있습니다."- 이것이 가능한 방법을 알지 못합니다. 문제의 LogCat 항목을 제공하고 분석을 설명해 주시겠습니까? 그 외에도, 대화 형 - 일시 중지 방식의 접근 방식이 올바르게 작동하고 처음에는 좋은 생각이라고 생각하는 이유는 무엇입니까? – CommonsWare

답변

1

나는 당신의 AsyncTask 다음과 같은 변화를 제안

@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() 정적 메소드 외부 클래스와 AsyncTask를 외부 개방을에 의해 대화 상자를 이동

+0

나는 donfuxx의 대답을 시도하고, Shayan이 제안한 변화를 만들었지 만 아무런 효과가 없다. –

+0

직렬화 코드의 시작과 끝에서 로그하는 logcat 메시지가 있기 때문에 주 스레드가 차단되고 있다고 말할 수 있습니다. 그 사이에 "Chippedographer에서 128 frames 건너 뛰었습니다!"라는 메시지가 표시 될 수 있습니다. 주 스레드에서 너무 많은 작업을 수행함 " –

0

시도

dialog = ProgressDialog.show(...) 

단지

task.execute(); 

전에를을 닫습니다 수 있어야한다 onPostExecute

관련 문제