Autore Topic: ProcessDialog con processo in background che utilizza Observer/Observable  (Letto 664 volte)

Offline Qwertid

  • Utente junior
  • **
  • Post: 50
  • Respect: 0
    • Mostra profilo
Ciao a tutti  :-)

Ho l'ennesimo problema che spero mi aiutiate a risolvere: mi spiego...

Ad un certo punto nella mia applicazione lancio un comando che per eseguirsi necessita di qualche secondo: tale comando oltre a manipolare strutture dati richiama anche il metodo update di Observer che mi aggiorna la grafica dell'activity corrente. Poichè, appunto, ci mette qualche secondo per eseguirsi, mi sarebbe piaciuto implementare un ProcessDialog ed è quello che ho fatto...

Codice (Java): [Seleziona]
        @Override
        protected void onPrepareDialog(int id, Dialog dialog) {
                switch (id) {
                case DIALOG_PROGRESS_ID:
                        Thread thread = new Thread(new Runnable() {
                                @Override
                                public void run() {
                                        computazione();
                                        dismissDialog(DIALOG_PROGRESS_ID);
                                }
                        });
                        thread.start();
                default:
                        break;
                }
        }

Provandolo sull'emulatore tutto funziona bene: quando vado a provarlo sul telefono in carne ed ossa ( :-P) crasha con l'errore "Only the original thread that created a view hierarchy can touch its views."

Avete idea di come possa risolvere questa anomalia? Usando un async task mi da lo stesso problema: ho paura che il problema stia in una specie di conflitto con Observer visto che nello stack di LogCat compare il metodo "notifyObserver()". Che ne pensate?

Grazie  :-)

Offline Gigiuz

  • Utente normale
  • ***
  • Post: 187
  • Respect: +23
    • Google+
    • gigiuzzo81
    • Gigiuz81
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy Note III
  • Play Store ID:
    GGXSoft
  • Sistema operativo:
    Windows 7 64bit, OS X (virtualized), Ubuntu
Re:ProcessDialog con processo in background che utilizza Observer/Observable
« Risposta #1 il: 04 Ottobre 2011, 01:36:20 CEST »
0
Come ti dice l'errore (e mi risulta strano non ti esca anche sull'emulatore...) nessun thread parallelo può interagire con gli elementi del main/ui thread.

Quasi sicuramente il problema sta nella chiamata di

Codice (Java): [Seleziona]
dismissDialog(DIALOG_PROGRESS_ID);
infilato nel thread concorrente. potresti invece fare una cosa del genere usando un AsyncTask:

Codice (Java): [Seleziona]
public class ComputazioneAsync extends AsyncTask<ClasseCheContieneComputazione, Void, Void> {

        private ProgressDialog dialog;
       
        /**
        * Con questo costruttore crei un nuovo AsyncTask passandogli
        * l'Activity che lo richiama come parametro
        */

        public ComputazioneAsync(Context context) {
                this.dialog = new ProgressDialog(context);
        }
       
        /**
         * Viene impostata e visualizzata una ProgressDialog
         * */

        @Override
        protected void onPreExecute() {
                dialog.setTitle("Elaborazione");
                dialog.setMessage("Computazione in corso,\nattendere prego...");
                dialog.show();
        }
       
        /**
        * Viene richiamato il tuo metodo computazione() in un thread separato
        */

        @Override
        protected Void doInBackground(ClasseCheContieneComputazione... arg0) {
                ClasseCheContieneComputazione miaClasse = arg0[0];
                miaClasse.computazione();
                return void;
        }
       
        /**
        * Alla fine dell'elaborazione precedente viene nascosta la ProgressDialog
        */

       @Override
        protected void onPostExecute(Integer result) {
                super.onPostExecute(result);
               
                dialog.dismiss();
                       
        }

}

Volendo puoi utilizzare:

Codice (Java): [Seleziona]
protected void onProgressUpdate(<Tipo>... progress);
ma questo presuppone che tu debba trovare un modo per comunicare un <tipo> di aggiornamento da computazione()...

Spero di esserti stato utile :)
Hai bisogno di implementare un sistema di "codici seriali di sblocco" nella tua applicazione? Dai un'occhiata alla mia libreria: RemoteUnlocker

Offline Qwertid

  • Utente junior
  • **
  • Post: 50
  • Respect: 0
    • Mostra profilo
Re:ProcessDialog con processo in background che utilizza Observer/Observable
« Risposta #2 il: 08 Ottobre 2011, 22:27:56 CEST »
0
Ciao!
Perdona l'abissale ritardo nella risposta ma ho dovuto un attimo sospendere le faccende androidiane  ;-)

Ho letto con molto interesse il tuo post ma non ho ben capito cosa fai in questa parte

Codice (Java): [Seleziona]
        /**
        * Viene richiamato il tuo metodo computazione() in un thread separato
        */

        @Override
        protected Void doInBackground(ClasseCheContieneComputazione... arg0) {
                ClasseCheContieneComputazione miaClasse = arg0[0];
                miaClasse.computazione();
                return void;
        }

Cosa significa quell'arg0? Devo in qualche modo passare alla classe un riferimento di ClasseCheContieneComputazione?

Graize mille di tutto  :-)

Offline Gigiuz

  • Utente normale
  • ***
  • Post: 187
  • Respect: +23
    • Google+
    • gigiuzzo81
    • Gigiuz81
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy Note III
  • Play Store ID:
    GGXSoft
  • Sistema operativo:
    Windows 7 64bit, OS X (virtualized), Ubuntu
R: Re:ProcessDialog con processo in background che utilizza Observer/Observable
« Risposta #3 il: 08 Ottobre 2011, 22:36:44 CEST »
0
Cosa significa quell'arg0? Devo in qualche modo passare alla classe un riferimento di ClasseCheContieneComputazione?

Graize mille di tutto  :-)

Bingo! Esattamente quando chiami il metodo execute(ClasseCheContieneComputazione... arg0) del tuo AsyncTask dal thread principale. :-)

Inviato dal mio GT-I9100 usando Tapatalk
Hai bisogno di implementare un sistema di "codici seriali di sblocco" nella tua applicazione? Dai un'occhiata alla mia libreria: RemoteUnlocker

Offline Qwertid

  • Utente junior
  • **
  • Post: 50
  • Respect: 0
    • Mostra profilo
Re:ProcessDialog con processo in background che utilizza Observer/Observable
« Risposta #4 il: 08 Ottobre 2011, 22:43:49 CEST »
0
Wow risposta rapidissima  :-)

Purtroppo, però, il problema è sempre lo stesso: crash con solito messaggio d'errore che solo il main thread può modificare la UI...  :-(

Offline Qwertid

  • Utente junior
  • **
  • Post: 50
  • Respect: 0
    • Mostra profilo
Re:ProcessDialog con processo in background che utilizza Observer/Observable
« Risposta #5 il: 08 Ottobre 2011, 22:52:29 CEST »
0
Aggiungo il logcat

Codice (Java): [Seleziona]
E/AndroidRuntime(  475): FATAL EXCEPTION: AsyncTask #1

E/AndroidRuntime(  475): java.lang.RuntimeException: An error occured while executing doInBackground()

E/AndroidRuntime(  475):        at android.os.AsyncTask$3.done(AsyncTask.java:200)

E/AndroidRuntime(  475):        at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)

E/AndroidRuntime(  475):        at java.util.concurrent.FutureTask.setException(FutureTask.java:124)

E/AndroidRuntime(  475):        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)

E/AndroidRuntime(  475):        at java.util.concurrent.FutureTask.run(FutureTask.java:137)

E/AndroidRuntime(  475):        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)

E/AndroidRuntime(  475):        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)

E/AndroidRuntime(  475):        at java.lang.Thread.run(Thread.java:1096)

E/AndroidRuntime(  475): Caused by: android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

E/AndroidRuntime(  475):        at android.view.ViewRoot.checkThread(ViewRoot.java:2802)

E/AndroidRuntime(  475):        at android.view.ViewRoot.invalidateChild(ViewRoot.java:607)

E/AndroidRuntime(  475):        at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:633)

E/AndroidRuntime(  475):        at android.view.ViewGroup.invalidateChild(ViewGroup.java:2505)

E/AndroidRuntime(  475):        at android.view.View.invalidate(View.java:5139)

E/AndroidRuntime(  475):        at android.view.View.setBackgroundDrawable(View.java:7486)

E/AndroidRuntime(  475):        at android.view.View.setBackgroundColor(View.java:7376)

E/AndroidRuntime(  475):        at shipwar.main.activity.PosizFlottaActivity.update(PosizFlottaActivity.java:145)

E/AndroidRuntime(  475):        at java.util.Observable.notifyObservers(Observable.java:139)

E/AndroidRuntime(  475):        at shipwar.main.lib.PlayerField.placeShip(PlayerField.java:53)

E/AndroidRuntime(  475):        at shipwar.main.lib.ShipWarManager.placeShip(ShipWarManager.java:1463)

E/AndroidRuntime(  475):        at shipwar.main.lib.ShipWarManager.placeFleet(ShipWarManager.java:1101)

E/AndroidRuntime(  475):        at shipwar.main.lib.ShipWarManager.piazzaFlotte(ShipWarManager.java:306)

E/AndroidRuntime(  475):        at shipwar.main.activity.ComputazioneAsync.doInBackground(ComputazioneAsync.java:36)

E/AndroidRuntime(  475):        at shipwar.main.activity.ComputazioneAsync.doInBackground(ComputazioneAsync.java:1)

E/AndroidRuntime(  475):        at android.os.AsyncTask$2.call(AsyncTask.java:185)

E/AndroidRuntime(  475):        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)

E/AndroidRuntime(  475):        ... 4 more

W/ActivityManager(   43):   Force finishing activity shipwar.main.activity/.PosizFlottaActivity

E/WindowManager(  475): Activity shipwar.main.activity.PosizFlottaActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@43e929d8 that was originally added here

E/WindowManager(  475): android.view.WindowLeaked: Activity shipwar.main.activity.PosizFlottaActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@43e929d8 that was originally added here

E/WindowManager(  475):         at android.view.ViewRoot.<init>(ViewRoot.java:247)

E/WindowManager(  475):         at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)

E/WindowManager(  475):         at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)

E/WindowManager(  475):         at android.view.Window$LocalWindowManager.addView(Window.java:424)

E/WindowManager(  475):         at android.app.Dialog.show(Dialog.java:241)

E/WindowManager(  475):         at shipwar.main.activity.ComputazioneAsync.onPreExecute(ComputazioneAsync.java:27)

E/WindowManager(  475):         at android.os.AsyncTask.execute(AsyncTask.java:391)

E/WindowManager(  475):         at shipwar.main.activity.PosizFlottaActivity.onCreate(PosizFlottaActivity.java:75)

E/WindowManager(  475):         at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)

E/WindowManager(  475):         at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)

E/WindowManager(  475):         at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)

E/WindowManager(  475):         at android.app.ActivityThread.access$2300(ActivityThread.java:125)

E/WindowManager(  475):         at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)

E/WindowManager(  475):         at android.os.Handler.dispatchMessage(Handler.java:99)

E/WindowManager(  475):         at android.os.Looper.loop(Looper.java:123)

E/WindowManager(  475):         at android.app.ActivityThread.main(ActivityThread.java:4627)

E/WindowManager(  475):         at java.lang.reflect.Method.invokeNative(Native Method)

E/WindowManager(  475):         at java.lang.reflect.Method.invoke(Method.java:521)

E/WindowManager(  475):         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)

E/WindowManager(  475):         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)

E/WindowManager(  475):         at dalvik.system.NativeStart.main(Native Method)

Offline Gigiuz

  • Utente normale
  • ***
  • Post: 187
  • Respect: +23
    • Google+
    • gigiuzzo81
    • Gigiuz81
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy Note III
  • Play Store ID:
    GGXSoft
  • Sistema operativo:
    Windows 7 64bit, OS X (virtualized), Ubuntu
R: ProcessDialog con processo in background che utilizza Observer/Observable
« Risposta #6 il: 08 Ottobre 2011, 23:37:13 CEST »
0
Potresti postare un po' di codice, compresa l'implementazione del AsyncTask?

Inviato dal mio GT-I9100 usando Tapatalk
Hai bisogno di implementare un sistema di "codici seriali di sblocco" nella tua applicazione? Dai un'occhiata alla mia libreria: RemoteUnlocker