2012-04-10 4 views
2

Ich habe einen Handler in einer Aktivität registriert. handleMessage() ruft notifyDataSetChanged auf einem Adapter auf. Die Dinge funktionieren, während die Aktivität den Fokus hat. Wenn ich jedoch aus der Aktivität heraus und wieder zurück navigiere, funktioniert notifyDataSetChanged() nicht.Handler-Aufruf an notifyDataSetChanged() nicht ausgeführt

FileAdapter ist ein ArrayAdapter. MergeAdapter ist eine benutzerdefinierte Klasse von CommonsWare. _mergeAdapter enthält _fileAdapter.

Aktivitätscode:

public void setUpDownloadHandler() { 
// Define the Handler that receives messages from the thread and update the progress 
_downloadHandler = new Handler() { 
    public void handleMessage(Message message) { 
     super.handleMessage(message); 
     String fileId = (String) message.obj; 
     int progress = message.arg1; 
     FileInfo tempFile = null; 
     for (FileInfo file: _files) { 
    if (file.getFileId().equals(fileId)) { 
        file.setDownloadProgress(progress); 
        tempFile = file; 
       } 
      } 
      if (tempFile != null) { 
       _files.remove(tempFile); 
       _files.add(tempFile); 
      } 
      _fileAdapter.notifyDataSetChanged(); 
      _mergeAdapter.notifyDataSetChanged(); 
     } 
    }; 
} 

Vorbei an den Handler:

RunnableTask task = new DownloadFileRunnableImpl(application, the_workspace_url, the_file_info, the_workspace_info.getTitle(), the_internal_storage_directory, 
       _downloadHandler); 

Hintergrund Thread-Code:

if(temp > previous) { 
    Message message = new Message(); 
    message.arg1 = _currentProgress.intValue(); 
    message.obj = _fileId; 
    _progressHandler.sendMessage(message); 
    previous = temp; 
} 

Die andere Information ist, dass ich das Bestehen der Handler durch eine Mappe und dann in das Lauffähige. Ich mache das, um den Hintergrund-Thread in einem Dienst auszuführen. Ich denke nicht, dass das das Problem ist.

EDIT: Es scheint, wie der Hundeführer nicht mit der Aktivität zum zweiten Mal wird es navigiert (vielleicht, weil onCreate schafft einen neuen Handler) zugeordnet ist. Gibt es eine Möglichkeit, den alten Handler neu zu assoziieren oder zu behalten?

Aktualisieren Die Aktivität wird zerstört, wenn sie den Fokus auf eine andere Aktivität verliert.

Antwort

1

Ich würde versuchen, eine Protokollnachricht in die onDestroy-Methode Ihrer Aktivität zu stellen, um zu sehen, ob sie zerstört wird, wenn Sie sich von Ihrer Aktivität entfernen. Ihre Aufgabe kann also den Handler der alten Aktivität enthalten.

+0

Ok. Wenn der Handler zerstört wird, verliert er nicht seine Verbindung mit dem Hintergrund-Thread und aktualisiert die neue Aktivität nicht? – benkdev

+0

das ist, was ich denke passiert ist. Es kann auch etwas anderes sein, deshalb sollten Sie nach der Log-Nachricht suchen. Oder Sie können es im Debug-Modus ausführen und eine Pause in der Aktivität onDestroy setzen und sehen, ob es aufgerufen wird. – flobacca

+0

Ich habe das überprüft und die Aktivität wird nicht zerstört, wenn ich mich von ihr entferne. Wenn ich zurück navigiere, erstellt es einen neuen Handler in onCreate(). – benkdev

0

Hier ist meine Antwort, ich setzte stark auf http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/FragmentRetainInstance.html

Wirklich nahm nur ihren Code und änderte es so, dass ich das Fragment jedes Mal wenn ich den Thread gestartet werden soll Remake haben (Arbeit) wieder. Und es kommuniziert mit der Aktivität über einen Handler.

public class Main extends Activity implements WorkProgressListener { 

private static final String TAG = "tag"; 

private Handler handler; 

private Button startWorkBtn; 

private ProgressDialog progressDialog; 

private boolean onSaveInstanceFlag = false; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    Log.i(TAG,"Main onCreate " + Utils.getThreadId()); 

    setContentView(R.layout.main); 

    handler = new ProgressHandler(); 

    startWorkBtn = (Button)this.findViewById(R.id.start_work_btn); 
    startWorkBtn.setEnabled(false); 
    startWorkBtn.setOnClickListener(new OnClickListener() { 
    @Override 
    public void onClick (View v) { 
     Log.i("tag","Main: startWorkBtn onClick "); 
     startWorkBtn.setEnabled(false); 
     FragmentManager fm = getFragmentManager(); 
     Fragment workF = (Fragment)fm.findFragmentByTag("work"); 
     if (null == workF) { 
      workF = new WorkFragment(); 
      Log.i(TAG,"Main new WorkF" + Utils.getThreadId()); 

      startProgressDialog(true); 
      startWorkBtn.setEnabled(false); 
      fm.beginTransaction().add(workF, "work").commit(); 
      Log.i(TAG,"Main add(workF) " + Utils.getThreadId()); 

     } 
     else { 
      // should never be able to get here. 
     }    
    }   
}); 

    FragmentManager fm = getFragmentManager(); 

    Fragment loadingFragment = fm.findFragmentByTag("work"); 
    Log.i(TAG,"Main findFragment " + Utils.getThreadId()); 

    if (null == loadingFragment) { 
     this.startWorkBtn.setEnabled(true); 
    } 
    else { 
     // could also decide to show progress dialog based on savedInstanceState 
     this.startProgressDialog(true); 
    } 

} // end onCreate 

@Override 
public void onRestart() { 
    Log.i(TAG,"Main onRestart " + Utils.getThreadId()); 
    super.onRestart(); 
    this.onSaveInstanceFlag = false; 
} 


@Override 
public void onResume() { 
    Log.i(TAG,"Main onResume " + Utils.getThreadId()); 
    super.onResume(); 
    this.onSaveInstanceFlag = false; 
} 


@Override 
public void onSaveInstanceState (Bundle savedInstanceState) { 
    Log.i(TAG,"Main onSaveInstanceState "+ Utils.getThreadId()); 

    this.onSaveInstanceFlag = true; 

    super.onSaveInstanceState(savedInstanceState); 
    if (null != this.progressDialog) { 
     savedInstanceState.putBoolean("progressDialog", true); 
    } 
    else { 
     savedInstanceState.putBoolean("progressDialog", false); 
    } 
} 

@Override 
public void onStop() { 
    Log.i(TAG,"Main onStop " + Utils.getThreadId()); 
    super.onStop(); 
} 

@Override 
public void onDestroy() { 
    Log.i(TAG,"Main onDestroy " + Utils.getThreadId());  
    super.onDestroy(); 
    this.closeProgressDialog(); 
    this.handler.removeCallbacksAndMessages(null); 
} 


public class ProgressHandler extends Handler { 

    @Override 
    public void handleMessage (Message msg) { 
     Log.i(TAG,"Main ProgressDialogHandler handleMessage"); 
     Bundle b = msg.getData();   
     boolean isDone = b.getBoolean("isDone"); 
     String tag = b.getString("tag"); 

     if (isDone && !onSaveInstanceFlag) { 
      FragmentManager fm = getFragmentManager(); 
      Fragment loader = (Fragment)fm.findFragmentByTag(tag); 

      fm.beginTransaction().remove(loader).commit(); 

      closeProgressDialog(); 
      Main.this.startWorkBtn.setEnabled(true); 
     } 
    }  
} 


@Override 
public void sendProgress(String tag, int progress, int max) { 
    if (progress == max) { 
     Log.i(TAG,"Main sendProgress " + Utils.getThreadId()); 
     Message message = handler.obtainMessage();   
     Bundle b = new Bundle(); 
     b.putBoolean("isDone", true); 
     b.putString("tag",tag); 
     message.setData(b); 
     this.handler.sendMessage(message); 
    }  

} 

private void startProgressDialog(boolean show) { 
    this.progressDialog = new ProgressDialog(this); 
    this.progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 
    this.progressDialog.setMessage("loading"); 
    this.progressDialog.setCancelable(false); 
    this.progressDialog.show(); 
} 

private void closeProgressDialog() { 
    if (null != this.progressDialog) { 
     progressDialog.cancel(); 
     this.progressDialog = null; 
    }  
} 

} // end Main 

public class WorkFragment erweitert Fragment {

private static final String TAG = "tag"; 

private boolean mReady = false; 
private boolean mQuiting = false; 

private boolean done = false; 

public WorkFragment() {} 

final Thread mThread = new Thread() { 
    @Override 
    public void run() { 

    synchronized(this) { 
      while (!mReady) { 
       Log.i(TAG,"WorkF notReady"+ Utils.getThreadId());    

       if (mQuiting) { 
        return; 
       } 
       try { 
        wait(); 
       } catch (InterruptedException e) { 
       } 
      } 
     } // end synchronized 


     Log.i(TAG,"WorkF starting work "+ Utils.getThreadId());    

     try { 
      Log.i(TAG,"WorkF about to sleep"+ Utils.getThreadId());    

      Thread.currentThread().sleep(10000l); 

      Log.i(TAG,"WorkF almost finished "+ Utils.getThreadId());    

      done = true; 

     } catch (InterruptedException e1) { 
      e1.printStackTrace(); 
     } 

     synchronized(this) { 
      while (!mReady) { 
       Log.i(TAG,"Activity notReady"+ Utils.getThreadId());     

       if (mQuiting) { 
        return; 
       } 
       try { 
        wait(); 
       } catch (InterruptedException e) { 
       } 
      } 

      ((WorkProgressListener)getActivity()).sendProgress(WorkFragment.this.getTag(), 100, 100); 

     } // end synchronized 2 
    } 

}; 


@Override 
public void onAttach(Activity activity) { 
    super.onAttach(activity); 
    Log.i(TAG,"WorkF, onAttach: "+ Utils.getThreadId()); 

} 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    Log.i(TAG,"WorkF, onCreate: "+ Utils.getThreadId()); 

    setRetainInstance(true); 

    mThread.start(); 
} 

@Override 
public void onActivityCreated(Bundle savedInstanceState) { 
    super.onActivityCreated(savedInstanceState); 
    Log.i(TAG,"WorkF, onActivityCreated: "+ Utils.getThreadId()); 

    if (done) { 
     ((WorkProgressListener)getActivity()).sendProgress(WorkFragment.this.getTag(), 100, 100); 
    } 

    synchronized (mThread) { 
     mReady = true; 
     mThread.notify(); 
    } 
} 

@Override 
public void onStart() 
{ 
    super.onStart(); 
    Log.i(TAG,"WorkF, onStart: "+ Utils.getThreadId()); 

} 

@Override 
public void onDestroy() { 
    synchronized (mThread) { 
     mReady = false; 
     mQuiting = true; 
     mThread.notify(); 
    } 

    super.onDestroy(); 
} 

@Override 
public void onDetach() { 
    synchronized (mThread) { 
     mReady = false; 
     mThread.notify(); 
    } 

    super.onDetach(); 
} 

public void restart() { 
    synchronized (mThread) { 
     mThread.notify(); 
    } 
} 
}// end WorkFragment 

public interface WorkProgressListener { 

public void sendProgress (String tag, int progress, int max); 

} 
+0

Die zweite synchronisierte Arbeitsanweisung wurde von einer for-Schleife in eine if-Anweisung geändert, sodass der Thread bei einer neuen Aktivität nicht bis unendlich wartet. if (null! = WorkFragment.this) {if (mReady) {((WorkProgressListener) .getActivity()). sendProgress (....):}} – flobacca

+0

oops- rewrite "also wenn eine neue Aktivität NICHT gemacht wird Faden wartet nicht bis unendlich " – flobacca