2013-08-29 17 views
7

Ich versuche, einen Ordner mit Android AsyncTask zu entpacken. Die Klasse (Decompress genannt) ist eine innere Klasse von Unzip, wobei Unzip selbst eine Nicht-Aktivitätsklasse ist. Der Pseudo-Code ist:Innere Klasse kann auf Werte zugreifen, aber nicht aktualisieren - AsyncTask

public class Unzip { 
    private String index; 
    private String unzipDest; //destination file for storing folder. 
    private Activity activity; 
    private boolean result;  //result of decompress. 

    public void unzip(String loc) { 

    Decompress workThread = new Decompress(loc, activity); 
    workThread.execute(); 
    if(unzip operation was successful) { 
     display(index); 
    } 

    //Class Decompress: 
class Decompress extends AsyncTask<Void, Integer, Boolean> { 

     private ProgressDialog pd = null; 
     private Context mContext; 
       private String loc; 
     private int nEntries; 
     private int entriesUnzipped; 

     public Decompress(String location, Context c) { 
         loc = location; 
      mContext = c; 
      nEntries = 0; 
      entriesUnzipped = 0; 
      Log.v(this.toString(), "Exiting decompress constructor."); 
     } 

     @Override 
     protected void onPreExecute() { 
      Log.v(this.toString(), "Inside onPreExecute."); 
      pd = new ProgressDialog(mContext); 
      pd.setTitle("Unzipping folder."); 
      pd.setMessage("Unzip in progress."); 
      pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 
      Log.v(this.toString(), "Showing dialog and exiting."); 
      pd.show(); 
     } 

       @Override 
     protected Boolean doInBackground(Void... params) { 
         //unzip operation goes here. 
         unzipDest = something; //unzip destination is set here. 

         if(unzip operation is successful) { 
          result = true; 
          index = url pointing to location of unzipped folder. 
         } else { 
         result = false; 
         } 
       } 

    @Override 
     protected void onPostExecute(Boolean result) { 
      if(result) { 
       if(pd != null) { 
        pd.setTitle("Success"); 
        pd.setMessage("folder is now ready for use."); 
        pd.show(); 
        pd.dismiss(); 
        pd = null; 
        Log.v(this.toString(), "Unzipped."); 

        index = unzipDest + "/someURL"; 
        Log.v(this.toString(), "index present in: " + index); 
       } 
      } else { 
       pd = ProgressDialog.show(mContext, "Failure", "Cannot unzip."); 
       pd.dismiss(); 
      } 
     } 
    } 

Probleme Ich bin vor:
1. Der Wert von unzipDest und index, in doInBackground aktualisiert, null bleiben Unzip und alle seine Objekte. Wie kann ich sicherstellen, dass die Werte aktualisiert bleiben?
2. Ich weiß, dass DoInBackground in einem Thread auftritt, der vom Haupt-UI-Thread getrennt ist. Bedeutet das, dass alle im neuen Thread aktualisierten Werte verloren gehen, sobald der Thread zurückkehrt?

Antwort

14

Wie kann ich sicherstellen, dass die Werte aktualisiert bleiben?

Sie werden aktualisiert, da sie Membervariablen sind. Da AsyncTask jedoch asynchron ist, werden sie möglicherweise noch nicht aktualisiert, wenn Sie sie überprüfen. Sie können eine interface verwenden, um einen Rückruf zu erstellen, wenn diese Werte aktualisiert werden. This SO answer covers how to do this

Bedeutet das, dass alle im neuen Thread aktualisierten Werte verloren gehen, sobald der Thread zurückkehrt?

Nein, sie sollten nicht "verloren" sein. Sie wurden wahrscheinlich nicht in der AsyncTask geändert, wenn Sie sie überprüfen.

Da dies nicht Ihr tatsächlicher Code ist, kann ich nicht sehen, wenn Sie versuchen, auf sie zuzugreifen, aber Sie können die interface Methode verwenden oder die Funktionen aufrufen, die diese Werte in onPostExecute() benötigen. Sie können auch eine null Prüfung durchführen, bevor Sie versuchen, auf sie zuzugreifen. Es hängt nur von der Funktionalität und dem Fluss ab, den Sie brauchen, um den besten Weg zu finden. Ich hoffe, das hilft.

bearbeiten

In der Antwort, die ich im Zusammenhang mit, können Sie die Activity sagen, dass Sie, dass interface verwenden und seine Methode überschreiben (n) mit implements AsyncResponse in Ihrer Activity Erklärung nach der separaten interface class

public class MainActivity implements AsyncResponse{ 
Schaffung

dann überschreiben Sie in Ihrer Activity noch die Methode, die Sie in dieser Klasse (void processFinish(String output);)

deklariert haben
@Override 
void processFinish(String output){ // using same params as onPostExecute() 
//this you will received result fired from async class of onPostExecute(result) method. 
    } 

dann wird dies in onPostExecute() aufgerufen, wenn der Hörer sieht, dass es mit delegate.processFinish(result);delegate ist eine Instanz AsyncResponse (Ihre Interface-Klasse)

public class AasyncTask extends AsyncTask{ 
public AsyncResponse delegate=null; 

    @Override 
    protected void onPostExecute(String result) { 
     delegate.processFinish(result); 
    } 

Interface Beispiel aus verknüpften Antwort oben und eingestellt/getan wird aus Gründen der Klarheit kommentiert. Seien Sie also sicher, diese Antwort zu verbessern, wenn es jemandem hilft.

+0

Schöne Antwort. OP - im Allgemeinen möchten Sie vielleicht über die Regeln und Typen von verschachtelten Klassen nach dem Java-Standard lesen: http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html –

+0

@codeMagic: Vielen Dank für Ihre Antwort. Ich möchte auf die Datei zugreifen können, deren URL in 'index' gespeichert wird, nachdem der Entpackvorgang in 'workThread.execute()' erfolgreich abgeschlossen wurde. In der Frage, mit der Sie verbunden sind, verstehe ich nicht, wie die Schnittstelle 'AsyncResponse' initialisiert wurde. Kannst du bitte Erklären? Vielen Dank. – Sriram

+0

@Sriram Ich habe bearbeitet. Ich hoffe das klärt es ein bisschen auf. Bitte versuchen Sie es und fragen Sie, wenn Sie stecken bleiben. – codeMagic

Verwandte Themen