Διαβίβαση δεδομένων μεταξύ θραυσμάτων. Android: μεταβίβαση αντικειμένων μεταξύ Δραστηριότητας

Ηλεκτρονική 10.04.2019
Επισκόπηση προγράμματος Η έκδοση υπολογιστή του Microsoft Excel Viewer θα επιτρέψει...

Αγγίσαμε το θέμα της μετάβασης μεταξύ Δραστηριοτήτων σε εφαρμογές Android. Και, συγκεκριμένα, συζητήσαμε τη μεταφορά δεδομένων από τη μια Δραστηριότητα στην άλλη. Η προφανής λύση intent.putExtra(NextActivity.FIELD_NAME, field_value)μας εξυπηρετεί καλά εφόσον μεταβιβάζουμε δεδομένα «απλών» τύπων: String, int, long ή arrays. Μόλις όμως προσπαθήσουμε να μεταφέρουμε ένα αντικείμενο από το μοντέλο δεδομένων μας με αυτόν τον τρόπο, αρχίζουν οι δυσκολίες.
Τα αντικείμενα μπορούν να μεταφερθούν με αυτόν τον τρόπο, αλλά πρέπει να υλοποιήσουν τη διεπαφή Serializable ή Parcelable. Η πρώτη επιλογή, σύμφωνα με κάποιες κριτικές που βρήκα, μειώνει την απόδοση της εφαρμογής. Δεύτερον - ας ρίξουμε μια πιο προσεκτική ματιά.
Ακολουθεί ένα παράδειγμα κλάσης από μια από τις εφαρμογές μου:

  1. δημόσια τάξη Email υλοποιεί Parcelable (
  2. ιδιωτική διεύθυνση συμβολοσειράς.
  3. ιδιωτικός τύπος συμβολοσειράς;
  4. ιδιωτικό email (δέμα σε ) (
  5. this .address = σε .readString();
  6. αυτό το .type = σε .readString();
  7. δημόσια συμβολοσειρά getAddress() (
  8. διεύθυνση επιστροφής;
  9. δημόσιο κενό setAddress (Διεύθυνση συμβολοσειράς) (
  10. αυτό .διεύθυνση = διεύθυνση;
  11. δημόσια συμβολοσειρά getType() (
  12. τύπος επιστροφής?
  13. δημόσιο κενό setType(String t) (
  14. αυτό .type = t;
  15. δημόσιο email(String a, String t) (
  16. this.address = a;
  17. αυτό .type = t;
  18. public int describeContents() (
  19. επιστροφή 0;
  20. δημόσιο στατικό τελικό Parcelable.Creator CREATOR = new Parcelable.Creator() (
  21. δημόσιο email createFromParcel(Parcel in ) (
  22. επιστροφή νέου email(in);
  23. δημόσιο email newArray(int size) (
  24. Επιστροφή νέου email.
  25. public void writeToParcel(Parcel parcel, int i) (
  26. parcel.writeString(διεύθυνση);
  27. parcel.writeString(type);
Όπως μπορείτε να δείτε, υλοποιεί τη διεπαφή Parcelable, που σημαίνει ότι μπορεί να μεταφερθεί εύκολα μεταξύ της Δραστηριότητας. Πώς το πετυχαίνουμε αυτό; Συμπληρώνουμε τη λογική της τάξης με μεθόδους Parcel-ization και De-parcel-ization του, με άλλα λόγια, αποθηκεύοντάς το στο Parcel και επαναφέροντάς το από αυτό. Το δέμα μπορεί να θεωρηθεί εδώ ως ένα είδος buffer στο οποίο μπορείτε να προσθέσετε δεδομένα οποιουδήποτε τύπου με μια συγκεκριμένη σειρά και στη συνέχεια (με την ίδια σειρά!) να τα εξαγάγετε από εκεί.
Η αποθήκευση των περιεχομένων των πεδίων κλάσης στο Parcel είναι πολύ απλή. Αυτό υλοποιείται στη μέθοδο writeToParcel. Για να επαναφέρουμε ένα αντικείμενο, προχωράμε ως εξής: Δημιουργούμε μια ένθετη κλάση Parcelable.Creator, στην οποία υλοποιούμε δύο μεθόδους. Το δεύτερο φαίνεται πάντα το ίδιο, αλλά το πρώτο είναι πολύ σημαντικό για εμάς: θα καλέσει έναν νέο κατασκευαστή της κατηγορίας μας, περνώντας του το Parcel. Στον κατασκευαστή πρέπει να εφαρμόσουμε την αντίστροφη λογική της μεθόδου writeToParcel, δηλ. αφαιρέστε τις τιμές των πεδίων κλάσης από το Parcel με την ίδια σειρά που γράφτηκαν εκεί. Στην περίπτωση των απλών πεδίων String, αυτό δεν είναι δύσκολο. Αν έχουμε πεδία τύπου ArrayList, τότε κάνουμε το εξής:
p.writeInt(phone.size());
για (int i = 0; i< phone.size(); i++) {
p.writeString(phone.get(i));
}
για διατήρηση και
int count = p.readInt();
για (int i = 0; i< count; i++) {
Συμβολοσειρά ph = p.readString();
phone.add(ph);
}
για ανάρρωση. Εδώ το p, όπως πιθανώς μαντέψατε, είναι ένα αντικείμενο της κλάσης Parcel και το τηλέφωνο είναι ένα πεδίο τύπου ArrayList.
Εάν τα πεδία της τάξης μας είναι οι άλλες τάξεις μας, τότε πρέπει επίσης να «τα διδάξουμε να ομαδοποιούν». Στη συνέχεια θα τοποθετήσουμε πεδία τέτοιων τύπων στο Parcel χρησιμοποιώντας τη μέθοδο
p .writeParcelable(organization, Parcelable.CONTENTS_FILE_DESCRIPTOR);
και να εξαγάγετε από εκεί χρησιμοποιώντας τη μέθοδο
οργάνωση = p .readParcelable(getClass().getClassLoader());

Η δημιουργία ενός καλού UI είναι δύσκολη, ειδικά αν δεν έχετε ακόμη μεγάλη εμπειρία σε αυτόν τον τομέα. Επομένως, εδώ είναι μια γρήγορη δοκιμή των γνώσεών σας για το ζήτημα: εάν έχετε συνηθίσει στο γεγονός ότι ένα νέο παράθυρο απαιτεί απαραίτητα μια δραστηριότητα ή ομαλή κινούμενη εικόναΓια κάποιο λόγο, εμφανίζονται σπασμοί σε ένα πρόσφατα γραμμένο πρόγραμμα - αυτό το άρθρο είναι για εσάς :)

Δραστηριότητα τσουγκράνας

Τα περισσότερα μαθήματα που παρουσιάζουν τα κόλπα της ανάπτυξης Android ξεκινούν με τον ίδιο τρόπο: ζητείται από άπειρους προγραμματιστές να ρίξουν όλα τα οπτικά στοιχεία απευθείας στη σήμανση XML της κύριας Δραστηριότητας. Μοιάζει κάπως έτσι:

Η δημόσια κλάση MainActivity επεκτείνει το AppCompatActivity ( @Override protected void onCreate(Bundle savedInstanceState) ( super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ...

Αυτό το είδος σχεδίασης γίνεται συνήθεια και το έργο γεμίζει με νέες Δραστηριότητες με όλο και πιο περίπλοκη σήμανση. Ως αποτέλεσμα - έστω και ελάχιστα χρήσιμη εφαρμογήγίνεται κατάφυτη με μια στοίβα Δραστηριότητα, καταβροχθίζοντας όλα ΕΜΒΟΛΟ, και πέτρες και κουκούλες πετούν στον προγραμματιστή στο Google Play.

Και όλα αυτά επειδή το λειτουργικό σύστημα Android δεν υπόσχεται να κρατήσει ζωντανές τις Δραστηριότητές σας. Όπως θυμάστε, αυτά τα συστατικά υπάρχουν ανεξάρτητα το ένα από το άλλο, έχοντας έναν ειδικό κύκλο ζωής. Εάν η Δραστηριότητα μεταβεί στην κατάσταση onPause, και αυτό συμβαίνει αρκετά συχνά, γίνεται η γάτα του Schrödinger: δεν μπορείτε να ξέρετε εκ των προτέρων αν θα είναι ζωντανή ή όχι.

Χρησιμοποιώντας πρόσθετες Δραστηριότητες για την εμφάνιση μενού και άλλων μικροπράξεων, θέτετε σε κίνδυνο τα πάντα λογικές συνδέσειςμέσα στην εφαρμογή. Οι δραστηριότητες συλλέγονται σε μια στοίβα και το λειτουργικό σύστημα μπορεί να ξεκινήσει να τις ξεφορτώνει μία προς μία ή σε μια ομάδα. Όταν ο χρήστης θέλει να επιστρέψει στο προηγούμενο παράθυρο, η Δραστηριότητα ενδέχεται να έχει ήδη καταστραφεί και ο χρήστης να εγκαταλείψει την εφαρμογή.

Εκτός από τα προβλήματα με τη διατήρηση της λογικής, υπάρχει επίσης η ρουτίνα υποστήριξης του κώδικα OOP: στενά συνδεδεμένη με Διεπαφές δραστηριότηταςΕίναι σχεδόν αδύνατο να αναπτυχθεί περαιτέρω. Απολέπιση, γρήγορη αντικατάστασηορισμένα στοιχεία σε άλλα, κινούμενα σχέδια - όλα αυτά θα είναι πολύ δύσκολο να εφαρμοστούν σε νέες εκδόσεις της εφαρμογής.

Χάρη στη μόδα για ένα ενιαίο οικοσύστημα, τα πάντα εφαρμογές για κινητάήταν γενικά πολύ παρόμοια. Απλά πρέπει να βρεις το μονοπάτι και να εξασκηθείς λίγο, και μετά η ποιότητα αρχίζει να αυξάνεται γρήγορα. Ακολουθώντας την αρχή "κριτική - προτείνω", θα γράψουμε τώρα μια εφαρμογή που υλοποιεί μια καθολική διεπαφή χρήστη. Αυτό θα είναι ενδιαφέρον όχι μόνο από ακαδημαϊκή άποψη - είμαι βέβαιος ότι μπορείτε εύκολα να ενσωματώσετε τον κώδικα που γράφτηκε σήμερα στα έργα σας. Ας ξεκινήσουμε λοιπόν!

Θραύσματα

Για να κάνει την εργασία με τη διεπαφή χρήστη ευκολότερη και ταχύτερη, η Google δημιούργησε ένα Fragment - μια τάξη - ένα επίπεδο μεταξύ της Δραστηριότητας και των οπτικών στοιχείων του προγράμματος. Από τη μία πλευρά, είναι ένα κοντέινερ για οποιαδήποτε αντικείμενα Προβολής που μπορούν να εμφανιστούν στον χρήστη. Από την άλλη - συνέχιση της Δραστηριότητας, από το οποίο το Fragment λαμβάνει όλες τις πληροφορίες σχετικά με τις αλλαγές στον κύκλο ζωής.

Τα Fragments, όπως η Activity, έχουν τα δικά τους (αν και πιο πρωτότυπα) κύκλος ζωής. Για παράδειγμα, είναι αδύνατο να εργαστείτε με τη διεπαφή χρήστη αμέσως μετά τη δημιουργία ενός τμήματος, πρέπει να περιμένετε να φορτωθούν όλα τα στοιχεία - μετά τη μέθοδο onCreate, θα εκτελεστεί η μέθοδος onCreateView, όπου μπορούν να φορτωθούν τα στοιχεία.

Η δημόσια κλάση FragmentOne επεκτείνει το Fragment ( ... δημόσια προβολή onCreateView(...) ( Προβολή προβολής=inflater.inflate(R.layout.fragment_one, container,false);

Σε ένα τμήμα, μπορείτε επίσης να παρακάμψετε τυχόν μεθόδους που παρακολουθούν την κατάσταση του παραθύρου. Έτσι, εάν η εφαρμογή πάει στο παρασκήνιο, το onPause θα εκτελεστεί στη Δραστηριότητα και, στη συνέχεια, η μέθοδος με ακριβώς το ίδιο όνομα θα εκτελεστεί εδώ. Αυτό μπορεί να είναι χρήσιμο - βολικό για αποσύνδεση από αντικείμενα τρίτων, όπως δεσμευμένες υπηρεσίες.

FragmentTransaction

Γνωρίζοντας ότι η εργασία με θραύσματα θα ήταν έντονη, η Google δημιούργησε ειδικά εργαλεία για αυτό εκ των προτέρων. Οι κλάσεις FragmentManager και FragmentTransaction συγκεντρώνουν όλες τις διεργασίες: δημιουργία νέων τμημάτων και διαγραφή τους, μεταφορά δεδομένων και ούτω καθεξής.

Δεν χρειάζεται να δημιουργήσετε ένα αντικείμενο FragmentManager, υπάρχει ήδη σε κάθε Δραστηριότητα, απλά πρέπει να λάβετε έναν σύνδεσμο προς αυτό. Και όλες οι ενέργειες θα περάσουν από το FragmentTransaction , το οποίο στη συνέχεια θα μεταφέρει ανεξάρτητα δεδομένα στον διαχειριστή τμημάτων.

FragmentManager manager = getSupportFragmentManager(); FragmentTransaction συναλλαγή = manager.beginTransaction();

Θα ήθελα να σημειώσω ότι οι τάξεις που λειτουργούν με τμήματα είναι διαθέσιμες σε δύο εκδόσεις. Συνιστώ να χρησιμοποιήσετε περισσότερο νέα έκδοση- αυτά είναι αυτά που έχουν τη γραμμή android.support.v4 στη διαδρομή εισαγωγής. Αυτό μεγάλη βιβλιοθήκηδημιουργήθηκε για τον οργανισμό συμβατότητα προς τα πίσω. Εταιρεία Googleαντιμετωπίζει με προσοχή τις συσκευές σε όλες τις εκδόσεις του λειτουργικού συστήματος και οι βιβλιοθήκες σάς επιτρέπουν να χρησιμοποιείτε καινοτομίες ανάπτυξης ακόμα και όταν εργάζεστε με το παλιό API.

Εισαγωγή android.support.v4.app.FragmentTransaction; εισαγωγή android.support.v4.app.Fragment;...

FrameLayout

Συχνά τα δεδομένα στη διεπαφή χρήστη προέρχονται δυναμικά, ανάλογα με τα τρέχοντα συμβάντα. Για να έχετε κάπου να τοποθετήσετε μια εικόνα ή ένα κείμενο, υπάρχει ένα ειδικό κοντέινερ - FrameLayout. Αυτό είναι το κύριο καθήκον του - να κρατήσει χώρο στην οθόνη για οποιοδήποτε αντικείμενο της κλάσης View, το οποίο μπορεί να φορτωθεί αργότερα. Σε τέτοια δοχεία ζουν και θραύσματα.

Μπορείτε να προσθέσετε ένα νέο τμήμα στο FrameLayout με διαφορετικούς τρόπους: Το FragmentTransaction έχει παρόμοια λειτουργικότητα για την αντικατάσταση και την προσθήκη μεθόδων.

Transaction.replace(R.id.frame_container, fragmentObject);

Παρά την εξωτερική ομοιότητα, πρέπει να έχετε μια καλή κατανόηση των αποτελεσμάτων που μπορείτε να επιτύχετε. Η μέθοδος αντικατάστασης λειτουργεί πολύ απλά - θα προσθέσει ένα κομμάτι και, αν υπήρχε κάτι στο κοντέινερ πριν, θα διαγράψει τα παλιά θραύσματα.

Transaction.add(R.id.frame_container, fragment);

Η μέθοδος προσθήκης δημιουργεί μια στοίβα θραυσμάτων και το καθένα νέα πρόκλησησπρώχνει ένα νέο στιγμιότυπο στην κορυφή της στοίβας. Είναι σημαντικό όταν εμφανίζεται ένα νέο κομμάτι, τα παλιά αντικείμενα στη στοίβα να μην λαμβάνουν ειδοποιήσεις και να ενεργούν σαν να μην είχε συμβεί τίποτα. Αυτό σημαίνει ότι η μέθοδος onPause για αυτούς δεν θα εκτελεστεί και θα συνεχίσουν να καταναλώνουν πόρους της συσκευής, αν και ο χρήστης δεν θα τους βλέπει πλέον.

Αυτή η σπατάλη της εκχωρημένης μνήμης μπορεί να δικαιολογηθεί, για παράδειγμα, εάν θέλετε να οργανώσετε την προεπεξεργασία δεδομένων: ένα τμήμα μπορεί να φορτώσει κάτι ενώ είναι αόρατο και στη συνέχεια να εμφανίσει το τελικό αποτέλεσμα.

Μπορεί να υπάρχουν πολλές ενέργειες με θραύσματα που θα συσσωρευτούν μέχρι να εκτελεστεί η μέθοδος δέσμευσης.

Transaction.commit();

Η συνέχεια είναι διαθέσιμη μόνο σε συνδρομητές

Επιλογή 1. Εγγραφείτε στο Hacker για να διαβάσετε όλο το υλικό στον ιστότοπο

Η συνδρομή θα σας επιτρέψει να καθορισμένη περίοδοδιαβάστε ΟΛΟ το υλικό επί πληρωμή στον ιστότοπο. Δεχόμαστε πληρωμήτραπεζικές κάρτες

, ηλεκτρονικό χρήμα και μεταφορές από λογαριασμούς παρόχου κινητής τηλεφωνίας.Εικόνα 2.

Κύκλος ζωής θραύσματος (κατά την εκτέλεση της λειτουργίας) Για να δημιουργήσετε ένα τμήμα, πρέπει να υποκατηγορήσετε την κλάση (ή μια υπάρχουσα υποκλάση της). Η τάξη έχει κώδικα παρόμοιο με το . Περιέχει μεθόδους επανάκλησης παρόμοιες με μεθόδους λειτουργίας, όπως , και . Στην πράξη, αν χρειαστεί να μετατρέψετε ένα υπάρχονΕφαρμογή Android

ώστε να χρησιμοποιεί θραύσματα, απλώς μετακινείτε τον κώδικα από τις μεθόδους επανάκλησης λειτουργίας στις αντίστοιχες μεθόδους επανάκλησης τμημάτων.

Συνήθως, πρέπει να εφαρμόσετε τις ακόλουθες μεθόδους κύκλου ζωής: Το σύστημα καλεί αυτήν τη μέθοδο όταν δημιουργεί ένα τμήμα. Κατά την υλοποίησή του, ο σχεδιαστής πρέπει να προετοιμάσει τα βασικά συστατικά του τμήματος που πρέπει να διατηρηθούν όταν το θραύσμα τεθεί σε παύση ή συνεχιστεί μετά τη διακοπή.Το σύστημα καλεί αυτήν τη μέθοδο την πρώτη φορά που εμφανίζεται

Υπάρχει επίσης ένας αριθμός υποκλάσεων που μπορεί να χρειαστεί να επεκταθούν αντί να χρησιμοποιηθεί η βασική κλάση:

Εμφανίστε ένα κινητό παράθυρο διαλόγου. Η χρήση αυτής της κλάσης για τη δημιουργία ενός πλαισίου διαλόγου είναι μια καλή εναλλακτική βοηθητικές μέθοδοιπλαίσιο διαλόγου στην τάξη. Αυτό συμβαίνει επειδή παρέχει τη δυνατότητα εισαγωγής ενός διαλόγου τμήματος σε μια πίσω στοίβα που βασίζεται στη λειτουργία για θραύσματα, επιτρέποντας στον χρήστη να επιστρέψει σε ένα κλειστό τμήμα.

Η εμφάνιση μιας λίστας στοιχείων που διαχειρίζονται προσαρμογείς (όπως το ) είναι παρόμοια με το . Αυτή η κλάση παρέχει πολλές μεθόδους για τη διαχείριση της λίστας προβολών, όπως μια μέθοδο επανάκλησης για το χειρισμό των κλικ.

Εμφάνιση μιας ιεραρχίας αντικειμένων με τη μορφή λίστας, παρόμοια με το . Αυτή η κλάση είναι χρήσιμη κατά τη δημιουργία μιας λειτουργίας Ρυθμίσεις σε μια εφαρμογή.

Προσθήκη διεπαφής χρήστη Ένα τμήμα χρησιμοποιείται συνήθως ως μέρος της διεπαφής χρήστη μιας δραστηριότητας και προσθέτει τη δική του διάταξη στη δραστηριότητα.Για να δημιουργήσετε μια διάταξη για ένα τμήμα, ο προγραμματιστής πρέπει να εφαρμόσει μια μέθοδο επανάκλησης που

σύστημα AndroidΚαλείται όταν έρθει η ώρα για το τμήμα να αποδώσει τη διάταξή του. Η υλοποίηση αυτής της μεθόδου πρέπει να επιστρέψει ένα αντικείμενο που είναι η ρίζα της διάταξης του τμήματος.

Σημείωμα.

Εάν το τμήμα είναι υποκλάση της κλάσης, η προεπιλεγμένη υλοποίηση επιστρέφει την κλάση από τη μέθοδο, επομένως δεν χρειάζεται να την εφαρμόσετε.

Για να επιστρέψετε μια διάταξη από μια μέθοδο, μπορείτε να τη διογκώσετε από μια μέθοδο που ορίζεται στο αρχείο XML. Για το σκοπό αυτό, η μέθοδος παρέχει ένα .

Για παράδειγμα, ο κώδικας για μια υποκλάση της κλάσης που φορτώνει τη διάταξη από το example_fragment.xml μπορεί να μοιάζει με αυτό:

Η δημόσια στατική κλάση ExampleFragment επεκτείνει το Fragment ( @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) ( // Διογκώστε τη διάταξη για αυτό το τμήμα επιστροφής inflater.inflate(R.layout.example), falsement); Δημιουργία διάταξηςΣτον παρακάτω κώδικα, η κατασκευή R.layout.example_fragment είναι μια αναφορά σε έναν πόρο διάταξης που ονομάζεται example_fragment.xml που είναι αποθηκευμένος στους πόρους της εφαρμογής.

Καθέκαστα Για να δημιουργήσετε μια διάταξη σε XML, ανατρέξτε στο άρθρο.Για ένα παράδειγμα λειτουργίας που χρησιμοποιεί ένα θραύσμα ως νήμα φόντου, χωρίς διεπαφή χρήστη, ανατρέξτε στο δείγμα κώδικα FragmentRetainInstance.java που περιλαμβάνεται στα δείγματα SDK (και είναι διαθέσιμο σε Android /APIDemos/app/src/main/java/com/example/android/apis/app/FragmentRetainInstance.java .

Διαχείριση Θραυσμάτων

Για να διαχειριστείτε τμήματα σε μια λειτουργία, χρειάζεστε μια κλάση. Για να το αποκτήσετε, πρέπει να καλέσετε τη μέθοδο από το opcode.

Παρακάτω είναι οι ενέργειες που μπορείτε να εκτελέσετε:

  • να λάβετε τα τμήματα που υπάρχουν σε μια δραστηριότητα χρησιμοποιώντας μια μέθοδο (για τμήματα που παρέχουν διεπαφή χρήστη στη διάταξη δραστηριότητας) ή (και για τα τμήματα που έχουν διεπαφή χρήστη και για τα τμήματα χωρίς διεπαφή χρήστη).
  • αφαιρέστε θραύσματα από τη στοίβα των μεταβάσεων χρησιμοποιώντας τη μέθοδο προς τα πίσω (προσομοίωση πατήματος ενός κουμπιού Πίσωμεταχειριζόμενος);
  • καταχωρήστε τη διαδικασία αλλαγής ακρόασης στην πίσω στοίβα χρησιμοποιώντας το .

Περισσότερες πληροφορίεςΑυτές και άλλες μέθοδοι περιγράφονται στην τεκμηρίωση της τάξης.

Όπως φαίνεται στην προηγούμενη ενότητα, μπορείτε να χρησιμοποιήσετε την κλάση Open, η οποία σας επιτρέπει να πραγματοποιείτε συναλλαγές σε τμήματα, όπως προσθήκη και διαγραφή.

Εκτέλεση συναλλαγών με θραύσματα

Το μεγάλο πλεονέκτημα της χρήσης θραυσμάτων σε μια λειτουργία είναι η δυνατότητα προσθήκης, αφαίρεσης, αντικατάστασης και εκτέλεσης άλλων πραγμάτων με αυτά ως απόκριση στην είσοδο του χρήστη. Οποιοδήποτε σύνολο αλλαγών που γίνονται σε μια λειτουργία ονομάζεται συναλλαγή. Αυτό μπορεί να γίνει χρησιμοποιώντας τα API στο . Κάθε συναλλαγή μπορεί να αποθηκευτεί σε μια πίσω στοίβα που διαχειρίζεται η λειτουργία. Αυτό θα επιτρέψει στον χρήστη να μετακινηθεί προς τα πίσω μέσω αλλαγών σε τμήματα (παρόμοια με την κίνηση προς τα πίσω μέσω δραστηριοτήτων).

Αλληλεπίδραση με τη λειτουργία

δημόσια στατική κλάση FragmentA επεκτείνει το ListFragment ( OnArticleSelectedListener mListener; ... @Override δημόσιο κενό onAttach(Δραστηριότητα δραστηριότητας) ( super.onAttach(activity); δοκιμάστε ( mListener = (OnArticleSelectedListener) δραστηριότητα; ) catch (ClassCastException eClass) activity.toString() + " πρέπει να υλοποιήσει το OnArticleSelectedListener" ) ) ... )

Εάν η λειτουργία δεν υλοποιούσε τη διεπαφή, το τμήμα δημιουργεί μια εξαίρεση. Εάν είναι επιτυχές, το στοιχείο mListener θα περιέχει μια αναφορά στην υλοποίηση της λειτουργίας της διεπαφής OnArticleSelectedListener, έτσι ώστε το Fragment A να μπορεί να μοιράζεται συμβάντα με τη λειτουργία καλώντας μεθόδους που ορίζονται από τη διεπαφή OnArticleSelectedListener. Για παράδειγμα, εάν το τμήμα Α είναι μια επέκταση της κλάσης , τότε κάθε φορά που ο χρήστης κάνει κλικ σε ένα στοιχείο λίστας, το σύστημα καλεί το τμήμα. Αυτή η μέθοδος καλεί με τη σειρά της τη μέθοδο onArticleSelected() για να χρησιμοποιήσει το συμβάν σε συνδυασμό με τη λειτουργία:

Η δημόσια στατική κλάση FragmentA επεκτείνει το ListFragment ( OnArticleSelectedListener mListener; ... @Override public void onListItemClick(ListView l, View v, int position, long id) ( // Προσθήκη αναγνωριστικού σειράς του στοιχείου στο οποίο έγινε κλικ με τον πάροχο περιεχομένου Uri Uri noteUri = ContentUris (ArticleColumns.CONTENT_URI, id // Αποστολή του συμβάντος και του Uri στη δραστηριότητα κεντρικού υπολογιστή mListener.onArticleSelected(noteUri) ...)

Η παράμετρος id που μεταβιβάστηκε στη μέθοδο είναι το αναγνωριστικό της σειράς που περιέχει το επιλεγμένο στοιχείο λίστας που χρησιμοποιεί η λειτουργία (ή άλλο τμήμα) για την ανάκτηση του άρθρου από το αντικείμενο εφαρμογής.

Για περισσότερες πληροφορίες σχετικά με τη συνεργασία με έναν πάροχο περιεχομένου, ανατρέξτε στο έγγραφο.

Προσθήκη στοιχείων στη γραμμή ενεργειών

Τα τμήματα μπορούν να προσθέσουν στοιχεία μενού σε δραστηριότητες (και επομένως σε ) εφαρμόζοντας το . Ωστόσο, για να δέχεται κλήσεις αυτή η μέθοδος, πρέπει να κληθεί κατά το χρόνο εκτέλεσης για να υποδείξει ότι το τμήμα σκοπεύει να προσθέσει στοιχεία στο μενού επιλογών (διαφορετικά το τμήμα δεν θα αποδεχτεί την κλήση μεθόδου).

Οποιαδήποτε στοιχεία προστίθενται από το τμήμα στο Μενού Επιλογών προστίθενται στα υπάρχοντα. Επιπλέον, το τμήμα λαμβάνει επανακλήσεις μεθόδου όταν ο χρήστης επιλέγει ένα στοιχείο μενού.

Ο προγραμματιστής μπορεί επίσης να καταχωρήσει μια προβολή στη διάταξη του τμήματός του για παροχή μενού περιβάλλοντος. Για να το κάνετε αυτό, καλέστε τη μέθοδο. Όταν ο χρήστης ανοίγει το μενού περιβάλλοντος, το τμήμα δέχεται μια κλήση μεθόδου. Όταν ο χρήστης επιλέγει ένα στοιχείο μενού, το τμήμα λαμβάνει μια κλήση μεθόδου.

σύστημα AndroidΑν και το τμήμα λαμβάνει μια επανάκληση στο συμβάν "επιλεγμένο στοιχείο μενού" για κάθε στοιχείο που προσθέτει, η δραστηριότητα λαμβάνει πρώτα την αντίστοιχη επανάκληση όταν ο χρήστης επιλέξει ένα στοιχείο μενού. Εάν η υπάρχουσα υλοποίηση επανάκλησης της δραστηριότητας για το επιλεγμένο συμβάν του στοιχείου μενού δεν χειρίζεται το επιλεγμένο στοιχείο, το συμβάν μεταβιβάζεται στη μέθοδο επανάκλησης στο τμήμα. Αυτό ισχύει για τα μενού επιλογών και τα μενού περιβάλλοντος.

Για λεπτομερείς πληροφορίες μενού, ανατρέξτε στους οδηγούς προγραμματιστή και

Διαχείριση κύκλου ζωής τμημάτων

Εικόνα 3. Επίδραση του κύκλου ζωής της δραστηριότητας στον κύκλο ζωής του τμήματος

Η διαχείριση του κύκλου ζωής ενός τμήματος είναι από πολλές απόψεις παρόμοια με τη διαχείριση του κύκλου ζωής μιας λειτουργίας. Όπως μια πράξη, ένα θραύσμα μπορεί να υπάρχει σε μία από τις τρεις καταστάσεις:

ΣυνέχισεΤο θραύσμα είναι ορατό κατά τη διάρκεια της επέμβασης. Σε αναστολήΜια άλλη δραστηριότητα εκτελείται και έχει εστίαση στο προσκήνιο, αλλά η δραστηριότητα που περιέχει το τμήμα εξακολουθεί να είναι ορατή (η δραστηριότητα στο προσκήνιο είναι μερικώς διαφανής ή δεν γεμίζει ολόκληρη την οθόνη). ΣταμάτησεΤο θραύσμα δεν είναι ορατό. Είτε η λειτουργία του κοντέινερ έχει σταματήσει είτε το κομμάτι έχει αφαιρεθεί από αυτό αλλά προστέθηκε στην πίσω στοίβα. Το σταματημένο τμήμα είναι ακόμα ενεργό (όλες οι πληροφορίες σχετικά με την κατάσταση και τα στοιχεία αποθηκεύονται στο σύστημα). Ωστόσο, δεν είναι πλέον ορατό στον χρήστη και θα καταστραφεί εάν καταστραφεί η λειτουργία.

Εδώ πάλι η αναλογία με τη λειτουργία είναι ορατή: ο προγραμματιστής μπορεί να αποθηκεύσει την κατάσταση του τμήματος με βοήθεια σε περίπτωση που καταστραφεί η διαδικασία λειτουργίας και ο προγραμματιστής πρέπει να επαναφέρει την κατάσταση του τμήματος όταν αναψυχήεπιχειρήσεις. Η κατάσταση μπορεί να αποθηκευτεί κατά την εκτέλεση μιας μεθόδου επανάκλησης σε ένα τμήμα και να αποκατασταθεί κατά την εκτέλεση του , ή . Για περισσότερες πληροφορίες σχετικά με την επιμονή, ανατρέξτε στο έγγραφο.

Η πιο σημαντική διαφορά κύκλου ζωής μεταξύ μιας λειτουργίας και ενός θραύσματος είναι ο τρόπος με τον οποίο αποθηκεύονται στα αντίστοιχα backstacks τους. Από προεπιλογή, τοποθετείται μια λειτουργία στην πίσω στοίβα που διαχειρίζεται το σύστημα για λειτουργίες όταν σταματάει (έτσι ώστε ο χρήστης να μπορεί να επιστρέψει σε αυτήν χρησιμοποιώντας το κουμπί Πίσω, όπως περιγράφεται στο άρθρο). Ταυτόχρονα, το τμήμα τοποθετείται στην πίσω στοίβα που βασίζεται στη λειτουργία μόνο όταν ο προγραμματιστής ζητά ρητά να αποθηκευτεί μια συγκεκριμένη παρουσία καλώντας μια μέθοδο κατά τη διάρκεια της συναλλαγής που διαγράφει το τμήμα.

Διαφορετικά, η διαχείριση του κύκλου ζωής ενός τμήματος μοιάζει πολύ με τη διαχείριση του κύκλου ζωής μιας λειτουργίας. Γι' αυτό πρακτικές συστάσειςισχύουν επίσης για θραύσματα. Ταυτόχρονα, ο προγραμματιστής πρέπει να κατανοήσει πώς ο κύκλος ζωής μιας λειτουργίας επηρεάζει τον κύκλο ζωής ενός τμήματος.

Προσοχή!Εάν χρειάζεστε ένα αντικείμενο μέσα σε ένα αντικείμενο κλάσης, μπορείτε να καλέσετε το . Ωστόσο, ο προγραμματιστής πρέπει να προσέχει να καλεί τη μέθοδο μόνο όταν το τμήμα είναι συνδεδεμένο σε μια δραστηριότητα. Εάν το τμήμα δεν είναι ακόμη συνδεδεμένο ή αποσυνδέθηκε στο τέλος του κύκλου ζωής του, η μέθοδος θα επιστρέψει μηδενική.

Ευθυγράμμιση με τον κύκλο ζωής της δραστηριότητας

Ο κύκλος ζωής της δραστηριότητας που περιέχει το θραύσμα επηρεάζει άμεσα τον κύκλο ζωής του θραύσματος, έτσι ώστε κάθε επανάκληση κύκλου ζωής δραστηριότητας έχει ως αποτέλεσμα παρόμοια επιστροφή κλήσης για κάθε θραύσμα. Για παράδειγμα, όταν μια λειτουργία δέχεται μια κλήση, κάθε τμήμα της δέχεται .

Ωστόσο, τα θραύσματα έχουν πολλά πρόσθετες μέθοδοιΕπανακλήσεις κύκλου ζωής που παρέχουν μοναδική αλληλεπίδραση με μια λειτουργία για την εκτέλεση ενεργειών όπως η δημιουργία και η καταστροφή ενός τμήματος διεπαφής χρήστη. Αυτές είναι οι μέθοδοι:

OnCreate() , το τμήμα μέσα σε αυτήν τη λειτουργία λαμβάνει απλώς μια μέθοδο επανάκλησης.

Όταν μια λειτουργία εισέρχεται στην κατάσταση "συνέχιση", μπορείτε ελεύθερα να προσθέσετε και να αφαιρέσετε θραύσματα σε αυτήν. Έτσι, ο κύκλος ζωής του θραύσματος μπορεί να τροποποιηθεί ανεξάρτητα μόνο όταν η λειτουργία παραμένει στην κατάσταση "επαναφοράς".

Ωστόσο, όταν η λειτουργία εξέρχεται από αυτήν την κατάσταση, η πρόοδος του θραύσματος στον κύκλο ζωής του πραγματοποιείται και πάλι από τη λειτουργία.

Παράδειγμα:

Για να συνοψίσουμε όλα όσα καλύπτονται σε αυτό το έγγραφο, ας δούμε ένα παράδειγμα λειτουργίας που χρησιμοποιεί δύο τμήματα για να δημιουργήσει μια διάταξη δύο πλαισίων. Η παρακάτω λειτουργία περιλαμβάνει ένα κομμάτι για την εμφάνιση μιας λίστας θεατρικών έργων του Σαίξπηρ και ένα άλλο για την εμφάνιση μιας σύνοψης του έργου που έχει επιλεγεί από τη λίστα. Το παράδειγμα δείχνει πώς πρέπει να οργανωθούν διαφορετικές διαμορφώσεις θραυσμάτων ανάλογα με τη διαμόρφωση της οθόνης.

σύστημα AndroidΟ πλήρης πηγαίος κώδικας για αυτήν τη λειτουργία βρίσκεται στην ενότητα.

Η κύρια λειτουργία εφαρμόζεται διάταξη με τον συνηθισμένο τρόπο, στη μέθοδο:

@Override protected void onCreate(Bundle savedInstanceState) ( super.onCreate(savedInstanceState); setContentView(R.layout.fragment_layout); )

Η διάταξη fragment_layout.xml χρησιμοποιείται εδώ:

Χρησιμοποιώντας αυτήν τη διάταξη, το σύστημα δημιουργεί ένα στιγμιότυπο της κλάσης TitlesFragment (λίστα παιχνιδιών) μόλις η λειτουργία φορτώσει τη διάταξη. Σε αυτήν την περίπτωση, το αντικείμενο (το οποίο θα περιέχει ένα τμήμα με μια σύνοψη) καταλαμβάνει χώρο στη δεξιά πλευρά της οθόνης, αλλά αρχικά παραμένει κενό. Όπως θα φανεί παρακάτω, το κομμάτι δεν τοποθετείται έως ότου ο χρήστης επιλέξει ένα στοιχείο στη λίστα.

Ωστόσο, δεν είναι όλες οι οθόνες αρκετά πλατιές ώστε να εμφανίζονται περίληψηδίπλα στη λίστα με τα έργα. Επομένως, η διάταξη που περιγράφεται παραπάνω χρησιμοποιείται μόνο σε οριζόντιο προσανατολισμό οθόνης και αποθηκεύεται στο αρχείο res/layout-land/fragment_layout.xml.

Όταν η συσκευή είναι μέσα προσανατολισμός πορτραίτου, το σύστημα εφαρμόζει την παρακάτω διάταξη, η οποία αποθηκεύεται στο αρχείο res/layout/fragment_layout.xml:

Σε αυτήν τη διάταξη, υπάρχει μόνο το αντικείμενο TitlesFragment. Αυτό σημαίνει ότι όταν η συσκευή είναι σε κατακόρυφο προσανατολισμό, είναι ορατή μόνο η λίστα των παιχνιδιών. Όταν ο χρήστης κάνει κλικ σε ένα στοιχείο λίστας σε αυτήν τη διαμόρφωση, η εφαρμογή ξεκινά μια νέα δραστηριότητα για να εμφανίσει τη σύνοψη αντί να φορτώσει ένα δεύτερο τμήμα.

Στη συνέχεια, μπορείτε να δείτε πώς υλοποιείται αυτό στις κλάσεις τμημάτων. Πρώτα έρχεται ο κωδικός για την τάξη TitlesFragment, η οποία εμφανίζει μια λίστα με τα έργα του Σαίξπηρ. Αυτό το απόσπασμα επεκτείνει την τάξη και χρησιμοποιεί τις συναρτήσεις της για να κάνει τη βασική εργασία με τη λίστα.

Καθώς εξετάζετε τον κώδικα, παρατηρήστε ότι υπάρχουν δύο πιθανές συμπεριφορές ως απόκριση όταν ένας χρήστης κάνει κλικ σε ένα στοιχείο λίστας. Ανάλογα με το ποια από τις δύο διατάξεις είναι ενεργή, είτε δημιουργείται ένα νέο τμήμα με περίληψη και εμφανίζεται ως μέρος μιας μεμονωμένης λειτουργίας (με την προσθήκη του τμήματος στο αντικείμενο), είτε εκτελείται νέα λειτουργία(εμφανίζοντας ένα θραύσμα).

Το δεύτερο τμήμα, DetailsFragment, εμφανίζει μια σύνοψη του παιχνιδιού που έχει επιλεγεί στη λίστα TitlesFragment:

Ας θυμηθούμε τον κώδικα της κλάσης TitlesFragment: εάν ο χρήστης κάνει κλικ σε ένα στοιχείο λίστας και την τρέχουσα διάταξη Δενπεριλαμβάνει την προβολή R.id.details (η οποία κατέχει το DetailsFragment), στη συνέχεια η εφαρμογή εκτελεί ένα DetailsActivity για να εμφανίσει τα περιεχόμενα του στοιχείου.

Η δημόσια στατική κλάση DetailsActivity επεκτείνει τη Δραστηριότητα ( @Override protected void onCreate(Bundle savedInstanceState) ( super.onCreate(savedInstanceState); if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) (τώρα // Εάν η οθόνη είναι σε // οριζόντια λειτουργία, μπορούμε να εμφανίσουμε το παράθυρο διαλόγου // εν σειρά με τη λίστα, ώστε να μην χρειαζόμαστε αυτήν τη δραστηριότητα. finish(); return; ) if (savedInstanceState == null) ( // Κατά την αρχική ρύθμιση, συνδέστε τις λεπτομέρειες fragment DetailsFragment(new DetailsFragment).setArguments(getIntent().getExtras().beginTransaction().

Σημειώστε ότι στη διαμόρφωση τοπίου, αυτή η δραστηριότητα ολοκληρώνεται μόνη της, έτσι ώστε η κύρια δραστηριότητα να μπορεί να πάρει τον έλεγχο και να εμφανίσει το DetailsFragment δίπλα στο TitlesFragment . Αυτό μπορεί να συμβεί εάν ο χρήστης ξεκινήσει το DetailsActivity σε κατακόρυφο προσανατολισμό και στη συνέχεια γυρίσει τη συσκευή σε οριζόντιος προσανατολισμός(προκαλώντας την επανεκκίνηση της τρέχουσας λειτουργίας).

Πρόσθετα δείγματα κώδικα χρησιμοποιώντας αποσπάσματα (και πλήρη αρχεία) πηγαίος κώδικαςαυτό το παράδειγμα) είναι διαθέσιμα στην εφαρμογή δείγματος API Demos (η οποία μπορεί να ληφθεί από το ).



Συνιστούμε να διαβάσετε

Κορυφή