55 votes

Mettre à jour l'interface utilisateur à partir du fil

Je souhaite mettre à jour mon interface utilisateur à partir d'un thread qui met à jour une barre de progression. Malheureusement, lors de la mise à jour de la "barre de progression" de la barre de progression, celle-ci disparaît! Changer la barre de progression de la barre de progression en onCreate() de l'autre côté fonctionne!

Aucune suggestion?

 public void onCreate(Bundle savedInstanceState) {
    res = getResources();
    super.onCreate(savedInstanceState);
    setContentView(R.layout.gameone);
    pB.setProgressDrawable(getResources().getDrawable(R.drawable.green)); //**Works**/
    handler.postDelayed(runnable, 1);       
}

private Runnable runnable = new Runnable() {
    public void run() {  
        runOnUiThread(new Runnable() { 
            public void run() 
            { 
                //* The Complete ProgressBar does not appear**/                         
                pB.setProgressDrawable(getResources().getDrawable(R.drawable.green)); 
            } 
        }); 
    }
}
 

64voto

Pentium10 Points 68884

Vous devez le faire avec l'aide de AsyncTask (intelligent backround fil) et ProgressDialog

AsyncTask permet une utilisation facile et de le thread d'INTERFACE utilisateur. Cette classe permet d'effectuer des opérations d'arrière-plan et publier les résultats sur le thread de l'INTERFACE utilisateur sans avoir à manipuler les threads et/ou les gestionnaires.

Une tâche asynchrone est défini par un calcul qui s'exécute sur un thread d'arrière-plan et dont le résultat est publié sur le thread d'INTERFACE utilisateur. Une tâche asynchrone est défini par 3 types génériques, appelés Params, le Progrès et la Raison, et de 4 étapes, appelé commencer, doInBackground, processProgress et de fin.

Les 4 étapes

Lorsqu'une tâche asynchrone est exécutée, la tâche passe par 4 étapes:

onPreExecute(), invoquée sur le thread d'INTERFACE utilisateur immédiatement après l'exécution de la tâche. Cette étape est normalement utilisé pour la configuration de la tâche, par exemple en affichant une barre de progression dans l'interface utilisateur.

doInBackground(Params...), invoquée sur le thread d'arrière-plan immédiatement après onPreExecute() termine son exécution. Cette étape est utilisée pour effectuer le calcul de fond, qui peut prendre beaucoup de temps. Les paramètres de la tâche asynchrone sont passés à cette étape. Le résultat du calcul doit être retourné par cette étape et sera renvoyé à la dernière étape. Cette étape peut également utiliser publishProgress(le Progrès...) de publier une ou plusieurs unités de progrès. Ces valeurs sont publiées sur le thread de l'INTERFACE utilisateur, dans le onProgressUpdate(le Progrès...) l'étape.

onProgressUpdate(Progress...), invoquée sur le thread de l'INTERFACE utilisateur après un appel à publishProgress(le Progrès...). Le moment de l'exécution n'est pas défini. Cette méthode est utilisée pour afficher toute forme de progrès dans l'interface utilisateur, tandis que le calcul d'arrière-plan est toujours en cours d'exécution. Par exemple, il peut être utilisé pour animer une barre de progression ou afficher les journaux dans un champ de texte.

onPostExecute(Result), invoquée sur le thread de l'INTERFACE utilisateur après le calcul de fond de finitions. Le résultat du calcul d'arrière-plan est transmis à cette étape en tant que paramètre. Le filetage des règles

Il y a quelques filetage règles qui doivent être suivies pour cette classe fonctionne correctement:

L'instance de la tâche doit être créé sur le thread de l'INTERFACE utilisateur. execute(Params...) doit être appelée sur le thread d'INTERFACE utilisateur. Ne pas appeler onPreExecute(), onPostExecute(Suite), doInBackground(Params...), onProgressUpdate(le Progrès...) manuellement. La tâche peut être exécutée qu'une seule fois (une exception sera levée si une deuxième exécution est tentée.)

Exemple de code
Ce que la carte ne dans cet exemple n'est pas important, plus important comprendre que vous avez besoin pour utiliser AsyncTask pour afficher une boîte de dialogue pour le progrès.

private class PrepareAdapter1 extends AsyncTask<Void,Void,ContactsListCursorAdapter > {
    ProgressDialog dialog;
    @Override
    protected void onPreExecute() {
        dialog = new ProgressDialog(viewContacts.this);
        dialog.setMessage(getString(R.string.please_wait_while_loading));
        dialog.setIndeterminate(true);
        dialog.setCancelable(false);
        dialog.show();
    }
    /* (non-Javadoc)
     * @see android.os.AsyncTask#doInBackground(Params[])
     */
    @Override
    protected ContactsListCursorAdapter doInBackground(Void... params) {
        cur1 = objItem.getContacts();
        startManagingCursor(cur1);

        adapter1 = new ContactsListCursorAdapter (viewContacts.this,
                R.layout.contact_for_listitem, cur1, new String[] {}, new int[] {});

        return adapter1;
    }

    protected void onPostExecute(ContactsListCursorAdapter result) {
        list.setAdapter(result);
        dialog.dismiss();
    }
}

26voto

Cookie Monster Points 2595

La plus solution la plus simple que j'ai vu pour la fourniture d'un court l'exécution du thread d'INTERFACE utilisateur se fait via la méthode post() de la vue. Cela est nécessaire, car l'INTERFACE utilisateur méthodes ne sont pas ré-entrant. L' la méthode est la suivante:

package android.view;

public class View;

public boolean post(Runnable action);

La méthode post() correspond à la SwingUtilities.invokeLater(). Malheureusement, je n'ai pas trouver quelque chose de simple qui correspond à le SwingUtilities.invokeAndWait(), mais on peut construire le plus tard basé sur le premier avec un moniteur et d'un drapeau.

Donc, ce que vous enregistrez par là, c'est la création d'un gestionnaire. Vous avez simplement besoin pour trouver votre point de vue et de les afficher sur elle. Vous pouvez trouver votre point de vue par findViewById() si vous avez tendance à travailler avec id-ed ressources. Le résultant le code est très simple:

/* inside your non-UI thread */

view.post(new Runnable() {
        public void run() {
            /* the desired UI update */
        }
    });
}

Remarque: par Rapport à SwingUtilities.invokeLater() la méthode Vue.post() retourne une valeur booléenne indiquant si l' la vue est associée à un événement de la file d'attente. Depuis que j'ai utilisé le invokeLater() resp. post() de toute façon que pour le feu et oublier, Je n'ai pas vérifier la valeur du résultat. Fondamentalement, vous devez appel post() seulement après onAttachedToWindow() a été appelée sur la vue.

Meilleures Salutations

10voto

pablochan Points 2047

Utilisez la classe AsyncTask (au lieu de Runnable). Il a une méthode appelée onProgressUpdate qui peut affecter l'interface utilisateur (elle est invoquée dans le thread d'interface utilisateur).

10voto

Arhimed Points 18116

Si vous utilisez Handler (je le vois et espérons que vous avez créé son instance sur le fil de l'interface utilisateur), n'utilisez pas runOnUiThread() dans votre runnable . runOnUiThread() est utilisé lorsque vous sortez d'un fil non-UI, cependant Handler exécutera déjà votre runnable sur le fil UI.

Essayez de faire comme ça:

 private Handler mHandler = new Handler();
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.gameone);
    res = getResources();
    // pB.setProgressDrawable(getResources().getDrawable(R.drawable.green)); **//Works**
    mHandler.postDelayed(runnable, 1);
}

private Runnable runnable = new Runnable() {
    public void run() {
        pB.setProgressDrawable(getResources().getDrawable(R.drawable.green));
        pB.invalidate(); // maybe this will even not needed - try to comment out
    }
};
 

9voto

schwiz Points 13679

Vous devez créer un Handler dans le fil de l'interface utilisateur, puis l'utiliser pour publier ou envoyer un message de votre autre fil afin de mettre à jour l'interface utilisateur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X