Είδαμε ότι το πλαίσιο περιβάλλοντος χρήστη JFace παρέχει βασική υποστήριξη για την εμφάνιση της προόδου εργασιών σε ένα πλαίσιο διαλόγου (δείτε την ενότητα Μακρόχρονες λειτουργίες για λεπτομέρειες). Στην ενότητα Υποδομή ταυτοχρονισμού, εξετάσαμε την υποστήριξη περιβάλλοντος εκτέλεσης πλατφόρμας για ταυτοχρονισμό και μακρόχρονες λειτουργίες. Τώρα θα εξετάσουμε τον τρόπο με τον οποίο το περιβάλλον χρήστη της πλατφόρμας βελτιώνει αυτή την υποδομή στο πακέτο org.eclipse.ui.progress. Αυτό το πακέτο παρέχει το περιβάλλον χρήστη για την εμφάνιση της προόδου εργασιών στον πάγκο εργασίας και ορίζει επιπρόσθετη υποστήριξη για εργασίες που εκτελούνται στο νήμα περιβάλλοντος χρήστη.
Καταρχήν, ας εξετάσουμε τα διαφορετικά είδη των λειτουργιών στο παρασκήνιο οι οποίες μπορούν να εκτελούνται και τον τρόπο εμφάνισής τους στο περιβάλλον χρήστη του πάγκου εργασίας:
Οι εργασίες οι οποίες ενεργοποιούνται από το χρήστη αποτελούν αυτές τις εργασίες που έχουν ενεργοποιηθεί από το χρήστη. Ο πάγκος εργασίας αυτόματα θα εμφανίσει τις εργασίες χρήστη σε ένα αποκλειστικό πλαίσιο διαλόγου προόδου με ένα κουμπί το οποίο επιτρέπει στο χρήστη να εκτελεί μια λειτουργία στο παρασκήνιο και να συνεχίσει να εργάζεται. Χρησιμοποιούνται καθολικές προτιμήσεις για την επισήμανση του κατά πόσο οι εργασίες χρήστη θα πρέπει να εκτελούνται πάντα στο παρασκήνιο. Οι εργασίες χρήστη ξεχωρίζουν ως τέτοιου είδους στο API εργασιών με τη χρήση του (Job#setUser). Παραδείγματα εργασιών χρήστη περιλαμβάνουν τη διεργασία δόμησης, την ανάληψη ελέγχου ενός έργου, το συγχρονισμό με το χώρο αποθήκευσης, την εξαγωγή μιας πρόσθετης λειτουργίας και την αναζήτηση.
Οι εργασίες οι οποίες ενεργοποιούνται αυτόματα έχουν ένα νόημα για τους χρήστες αλλά δεν εκκινούνται από το χρήστη. Αυτές οι εργασίες εμφανίζονται στην προβολή προόδου και στη γραμμή κατάστασης αλλά δεν θα εμφανιστεί ένα αποκλειστικό πλαίσιο διαλόγου κατά την εκτέλεσή τους. Παραδείγματα αυτών των εργασιών περιλαμβάνουν την αυτόματη δόμηση και τον προγραμματισμένο συγχρονισμό.
Οι λειτουργίες συστήματος δεν ενεργοποιούνται από το χρήστη και μπορούν να θεωρηθούν ως λεπτομέρεια υλοποίησης πλατφόρμας. Αυτές οι εργασίες δημιουργούνται ορίζοντας τον ενδείκτη του συστήματος χρησιμοποιώντας το (Job#setSystem). Παραδείγματα εργασιών συστήματος περιλαμβάνουν εργασίες οι οποίες συμπληρώνουν αργά τα όργανα ή υπολογίζουν διακριτικά και σημειώσεις για προβολές.
Δεδομένου ενός περιβάλλοντος όπου αρκετά μπορούν να συμβαίνουν ταυτόχρονα, ένας χρήστης χρειάζεται τα ακόλουθα:
Μια ένδειξη ότι έχει εκκινήσει μια μακρόχρονη λειτουργία.
Οι εργασίες χρήστη εμφανίζονται στο χρήστη σε ένα πλαίσιο διαλόγου προόδου δίνοντας άμεσες πρόσθετες πληροφορίες, ενώ οι αυτόματα ενεργοποιημένες εργασίες εμφανίζονται στη γραμμή κατάστασης και την προβολή προόδου. Οι εργασίες που επηρεάζουν ένα τμήμα θα πρέπει να είναι προγραμματισμένες ή καταχωρημένες με το τμήμα αυτό ούτως ώστε να μπορεί ο πάγκος εργασίας να παρέχει υποδείξεις στο χρήστη για κάτι που εκτελείται και επηρεάζει το τμήμα.
Ένδειξη ότι μια λειτουργία έχει ολοκληρωθεί.
Ο χρήστης μπορεί εύκολα να γνωρίζει πότε ολοκληρώνεται μια εργασία χρήστη επειδή κλείνει το πλαίσιο διαλόγου προόδου. Για εργασίες που δεν εκτελεί ο χρήστης διατίθενται μερικοί μηχανισμοί πρόσθετων πληροφοριών. Εάν η εργασία είναι προγραμματισμένη ή καταχωρημένη με ένα τμήμα τότε η υπόδειξη προόδου του τμήματος θα εμφανίσει το πότε αυτή ολοκληρώθηκε. Εάν μια εργασία επιστρέψει ένα σφάλμα, μια ένδειξη σφάλματος θα εμφανιστεί κάτω δεξιά της γραμμή κατάστασης εμφανίζοντας μια υπόδειξη ότι έχει παρουσιαστεί ένα σφάλμα.
Ένδειξη ενδιαφέροντων νέων αποτελεσμάτων ή νέων πληροφοριών χωρίς να χάνεται η εστίαση με τη χρήση ενός πλαισίου διαλόγου.
Μια εργασία χρήστη μπορεί να εμφανίσει απευθείας τα αποτελέσματα στο χρήστη όταν ολοκληρωθεί η λειτουργία. Για εργασίες που δεν εκτελεί ο χρήστης συνιστάται η χρήση διαφορετικού τρόπου εμφάνισης αποτελεσμάτων από το πλαίσιο διαλόγου, ώστε ο χρήστης να μην διακόπτεται. Για παράδειγμα, μια προβολή θα μπορούσε να ανοιχθεί κατά την εκκίνηση της λειτουργίας και τα αποτελέσματα να εμφανίζονταν σε αυτή την προβολή χωρίς να διακόπτεται η ροή εργασιών του χρήστη. Επιπλέον, οι ιδιότητες εργασιών μπορούν να προστεθούν στην εργασία για να δηλώσουν ότι θα πρέπει να διατηρηθούν στην προβολή προόδου και ότι παρέχουν μια ενέργεια η οποία θα εμφανίσει τα αποτελέσματα. Σε αυτή την περίπτωση, μια προειδοποιητική ένδειξη θα εμφανιστεί στην κάτω δεξιά γωνία της γραμμής κατάστασης όταν μια εργασία παραμένει στην προβολή προόδου έχει τα αποτελέσματα για την εμφάνισή τους στο χρήστη.
Μια γενική αίσθηση ελέγχου των λειτουργιών που εκτελούνται, με τη δυνατότητα παρακολούθησης και ακύρωσης των λειτουργιών στο παρασκήνιο.
Οι εργασίες χρήστη παρέχουν τον καλύτερο έλεγχο για το χρήστη αφού μπορούν να ακυρωθούν εύκολα και παρέχουν ισχυρή ένδειξη των λειτουργιών αποκλεισμού και των ταυτόχρονων λειτουργιών που εκτελούνται μέσω της καρτέλας Λεπτομέρειες στο πλαίσιο διαλόγου προόδου. Σημειώστε ότι το βελτιωμένο πλαίσιο διαλόγου προόδου το οποίο παρέχει την περιοχή Λεπτομέρειες εμφανίζεται μόνο όταν οι πρόσθετες λειτουργίες χρησιμοποιούν τη διεπαφή IProgressService#busyCursorWhile ή τη διεπαφή IProgressService#runInUI.
Επιπλέον, η προβολή προόδου παρέχει πρόσβαση σε εργασίες που εκτελούνται.
Σταθερή αναφορά προόδου από όλες τις εγκατεστημένες πρόσθετες λειτουργίες.
Το πλεονέκτημα της χρήσης του API υπηρεσιών προόδου είναι ότι οι χρήστες λαμβάνουν μια σταθερή εμπειρία της προόδου.
Η υπηρεσία προόδου του πάγκου εργασίας (IProgressService) αποτελεί την κύρια διεπαφή της υποστήριξης προόδου του πάγκου εργασίας. Μπορεί να ληφθεί από τον πάγκο εργασίας και κατόπιν να χρησιμοποιηθεί για την εμφάνιση της προόδου τόσο για τις λειτουργίες στο παρασκήνιο, όσο και για τις λειτουργίες που εκτελούνται στο νήμα του περιβάλλοντος χρήστη. Ο κύριος στόχος αυτής της κλάσης είναι να παρέχει μια ολοκληρωμένη επιλογή για την εκτέλεση λειτουργιών, ώστε οι προγραμματιστές πρόσθετων λειτουργιών να μην χρειάζεται να αποφασίζουν ποιος μηχανισμός θα πρέπει να χρησιμοποιηθεί για την εμφάνιση της προόδου σε μια δεδομένη κατάσταση. Ένα άλλο πλεονέκτημα είναι ότι το πλαίσιο διαλόγου προόδου που εμφανίζεται με αυτές τις μεθόδους παρέχει μια καλή υποστήριξη για την ένδειξη του πότε μια λειτουργία εμποδίζεται από μια άλλη και δίνει στο χρήστη τον έλεγχο να επιλύσει αυτή τη διένεξη. Όπου αυτό είναι δυνατόν, οι μακρόχρονες λειτουργίες θα πρέπει να εκτελούνται με τη χρήση της IProgressService#busyCursorWhile:
IProgressService progressService = PlatformUI.getWorkbench().getProgressService(); progressService.busyCursorWhile(new IRunnableWithProgress(){ public void run(IProgressMonitor monitor) { //do non-UI work } });
Αυτή η μέθοδος αρχικά θα χρησιμοποιήσει έναν απασχολημένο δρομέα και θα τον αντικαταστήσει με ένα πλαίσιο διαλόγου προόδου εάν η λειτουργία διαρκέσει περισσότερο από ένα καθορισμένο χρονικό όριο. Το πλεονέκτημα αυτής της μεθόδου συγκριτικά με τη χρήση ενός πλαισίου προόδου είναι ότι το πλαίσιο διαλόγου δεν θα εμφανιστεί εάν η λειτουργία είναι μικρής διάρκειας. Εάν η λειτουργία σας πρέπει να ενημερώσει το περιβάλλον χρήστη, μπορείτε να χρησιμοποιήσετε τη μέθοδο Display.asyncExec ή την Display.syncExec για να εκτελέσετε τον κώδικα ο οποίος τροποποιεί το περιβάλλον χρήστη.
Εάν μια λειτουργία πρέπει να εκτελεστεί στο σύνολό της στο νήμα του περιβάλλοντος χρήστη, τότε θα πρέπει να χρησιμοποιηθεί η IProgressService#runInUI. Αυτή η μέθοδος θα εμφανίσει επίσης ένα πλαίσιο διαλόγου εάν η λειτουργία εμποδιστεί και θα παραχωρήσει τον έλεγχο στο χρήστη.
progressService.runInUI( PlatformUI.getWorkbench().getProgressService(), new IRunnableWithProgress() { public void run(IProgressMonitor monitor) { //do UI work } }, Platform.getWorkspace().getRoot());
Ως τιμή της τρίτης παραμέτρου μπορεί να είναι null ή ένας προγραμματισμένος κανόνας για τη λειτουργία. Σε αυτό το παράδειγμα, καθορίζουμε τον κεντρικό κατάλογο του χώρου εργασίας, ο οποίος ουσιαστικά θα κλειδώσει το χώρο εργασίας ενώ εκτελείται αυτή η λειτουργία περιβάλλοντος χρήστη.
Μπορείτε επίσης να καταχωρήσετε ένα εικονίδιο για μια οικογένεια εργασιών με την υπηρεσία προόδου, ούτως ώστε η προβολή προόδου να μπορεί να εμφανίσει το εικονίδιο δίπλα στην εκτελούμενη εργασία. Δείτε παρακάτω ένα παράδειγμα το οποίο δείχνει τον τρόπο με τον οποίο μια οικογένεια εργασιών αυτόματης δόμησης συσχετίζεται με το εικονίδιό της:
IProgressService service = PlatformUI.getWorkbench().getProgressService(); ImageDescriptor newImage = IDEInternalWorkbenchImages.getImageDescriptor( IDEInternalWorkbenchImages.IMG_ETOOL_BUILD_EXEC); service.registerIconForFamily(newImage, ResourcesPlugin.FAMILY_MANUAL_BUILD); service.registerIconForFamily(newImage, ResourcesPlugin.FAMILY_AUTO_BUILD);
Η διεπαφή IWorkbenchSiteProgressService περιλαμβάνει το API τον προγραμματισμό εργασιών, οι οποίες αλλάζουν την εμφάνιση ενός τμήματος του πάγκου εργασίας κατά την εκτέλεση της εργασίας. Εάν η πρόσθετη λειτουργία σας εκτελεί λειτουργίες στο παρασκήνιο οι οποίες επηρεάζουν την κατάσταση ενός τμήματος, μπορείτε να προγραμματίσετε την εργασία μέσω του τμήματος και ο χρήστης θα λάβει πρόσθετες πληροφορίες ότι το τμήμα είναι απασχολημένο. Ακολουθεί ένα παράδειγμα:
IWorkbenchSiteProgressService siteService = (IWorkbenchSiteProgressService)view.getSite().getAdapter(IWorkbenchSiteProgressService.class); siteService.schedule(job, 0 /* now */, true /* use the half-busy cursor in the part */);
Ο πάγκος εργασίας ορίζει ιδιότητες σχετικές με την πρόοδο για εργασίες στην IProgressConstants. Αυτές μπορούν να χρησιμοποιηθούν για τον έλεγχο του τρόπου με τον οποίο μια εργασία εμφανίζεται στην προβολή προόδου. Μπορούν να χρησιμοποιηθούν ώστε η προβολή προόδου να διατηρήσει (IProgressConstants#KEEP_PROPERTY) την εργασία σας στην προβολή αφού αυτή ολοκληρωθεί ή να διατηρεί μόνο μια εργασία (IProgressConstants#KEEPONE_PROPERTY) κάθε φορά στην προβολή. Μπορείτε επίσης να συσχετίσετε μια ενέργεια (IProgressConstants#ACTION_PROPERTY) με μια εργασία. Όταν μια εργασία διαθέτει μια συσχετισμένη ενέργεια, η προβολή προόδου εμφανίζει μια υπερδιασύνδεση, ώστε ο χρήστης να μπορεί να εκτελέσει την ενέργεια. Μπορείτε επίσης να ανακαλύψετε εάν μια εργασία χρήστη εμφανίζεται τη δεδομένη στιγμή σε ένα πλαίσιο διαλόγου προόδου (IProgressConstants#PROPERTY_IN_DIALOG). Παρέχεται μια υπόδειξη κάτω δεξιά στη γραμμή κατάστασης όταν διατίθεται μια ενέργεια. Το ακόλουθο παράδειγμα χρησιμοποιεί αυτές τις ιδιότητες:
Job job = new Job("Do Work") { public IStatus run(IProgressMonitor monitor) { // do some work. // Keep the finished job in the progress view only if it is not running in the progress dialog Boolean inDialog = (Boolean)getProperty(IProgressConstants.PROPERTY_IN_DIALOG); if(!inDialog.booleanValue()) setProperty(IProgressConstants.KEEP_PROPERTY, Boolean.TRUE); } }; job.setProperty(IProgressConstants.ICON_PROPERTY, Plugin.getImageDescriptor(WORK_IMAGE)); IAction gotoAction = new Action("Results") { public void run() { // show the results } }; job.setProperty(IProgressConstants.ACTION_PROPERTY, gotoAction); job.setUser(true); job.schedule();
Όπου αυτό είναι δυνατόν, οι μακρόχρονες λειτουργίες θα πρέπει να εκτελούνται εκτός του νήματος περιβάλλοντος χρήστη. Ωστόσο, αυτό δεν μπορεί να αποφευχθεί πάντα όταν ο σκοπός της λειτουργίας είναι η ενημέρωση του περιβάλλοντος χρήστη. Η ενότητα Θέματα νημάτωσης SWT εξηγεί τον τρόπο επίτευξης αυτού με τη χρήση της επιλογής SWT Εμφάνιση. Ο πάγκος εργασίας ορίζει μια ειδική εργασία , την UIJob, τις οποίας οι μέθοδοι εκτέλεσης εκτελούνται εντός μιας SWT asyncExec. Οι υποκλάσεις της UIJob θα πρέπει να υλοποιούν τη μέθοδο runInUIThread αντί της μεθόδου run.
Η WorkbenchJob επεκτείνει την UIJob ώστε η εργασία να μπορεί να προγραμματιστεί ή να εκτελεστεί μόνο όταν εκτελείται ο πάγκος εργασίας. Όπως πάντα, θα πρέπει να αποφεύγετε την υπερβολική εργασία στο νήμα του περιβάλλοντος χρήστη επειδή το περιβάλλον χρήστη δεν θα ανανεωθεί κατά τη διάρκεια της εργασίας περιβάλλοντος χρήστη.