Πώς να χρησιμοποιήσετε τον κύκλο ζωής και την κατάσταση της δραστηριότητας, Πώς να χρησιμοποιήσετε τον κύκλο ζωής και την κατάσταση της δραστηριότητας

1. Καλώς ήρθατε

Αυτό το πρακτικό εργαστήριο κωδικών αποτελεί μέρος της Ενότητας 1: Ξεκινήστε στο μάθημα Android Developer Fundamentals (Έκδοση 2). Θα αποκομίσετε τη μεγαλύτερη αξία από αυτό το μάθημα, εάν εργαστείτε μέσω των εργαστηρίων κωδικών με τη σειρά:

  • Για την πλήρη λίστα των εργαστηρίων κωδικών στο μάθημα, ανατρέξτε στο Codelabs for Android Developer Fundamentals (V2).
  • Για λεπτομέρειες σχετικά με το μάθημα, συμπεριλαμβανομένων συνδέσμων προς όλα τα εννοιολογικά κεφάλαια, τις εφαρμογές και τις διαφάνειες, ανατρέξτε στις Βασικές αρχές προγραμματιστή Android (Έκδοση 2).

Εισαγωγή

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

Διπλό πρόβλημα

Κάθε στάδιο στον κύκλο ζωής μιας δραστηριότητας έχει μια αντίστοιχη μέθοδο επανάκλησης: onCreate(), onStart(), onPause() και ούτω καθεξής. Όταν μια δραστηριότητα αλλάζει κατάσταση, καλείται η συσχετισμένη μέθοδος επανάκλησης. Έχετε ήδη δει μία από αυτές τις μεθόδους: onCreate(). Παρακάμπτοντας οποιαδήποτε από τις μεθόδους επιστροφής κλήσης κύκλου ζωής στις κλάσεις Δραστηριότητας, μπορείτε να αλλάξετε την προεπιλεγμένη συμπεριφορά της δραστηριότητας ως απόκριση σε ενέργειες χρήστη ή συστήματος.

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

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

Προαπαιτούμενα

Θα πρέπει να είστε σε θέση:

  • Δημιουργήστε και εκτελέστε ένα έργο εφαρμογής στο Android Studio .
  • Προσθέστε δηλώσεις καταγραφής στην εφαρμογή σας και προβάλετε αυτά τα αρχεία καταγραφής στο παράθυρο Logcat.
  • Κατανοήστε και δουλέψτε με μια Δραστηριότητα και μια Πρόθεση και να αλληλεπιδράτε άνετα μαζί τους.

Τι θα μάθετε

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

Τι θα κάνεις

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

2. Επισκόπηση εφαρμογής

Σε αυτό το πρακτικό προσθέτετε στην εφαρμογή TwoActivities . Η εφαρμογή φαίνεται και συμπεριφέρεται περίπου όπως στο τελευταίο εργαστήριο κωδικών. Περιέχει δύο υλοποιήσεις Δραστηριότητας και δίνει στον χρήστη τη δυνατότητα να στέλνει μεταξύ τους. Οι αλλαγές που κάνετε στην εφαρμογή σε αυτό το πρακτικό δεν θα επηρεάσουν την ορατή συμπεριφορά χρήστη της.

3. 3. Εργασία 1: Προσθήκη επανακλήσεων κύκλου ζωής στο TwoActivities

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

1.1 (Προαιρετικό) Αντιγράψτε το έργο TwoActivities

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

1.2 Εφαρμογή επανακλήσεων στο MainActivity

  1. Ανοίξτε το έργο TwoActivities στο Android Studio και ανοίξτε το MainActivity στο παράθυρο Project > Android.
  2. Στη μέθοδο onCreate(), προσθέστε τις ακόλουθες δηλώσεις καταγραφής:
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
  1. Προσθέστε μια παράκαμψη για την επανάκληση onStart(), με μια δήλωση στο αρχείο καταγραφής για αυτό το συμβάν:
@Override
public void onStart(){
    super.onStart();
    Log.d(LOG_TAG, "onStart");
}

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

  1. Χρησιμοποιήστε τη μέθοδο onStart() ως πρότυπο για να εφαρμόσετε τις επιστροφές κλήσεων κύκλου ζωής onPause(), onRestart(), onResume(), onStop() και onDestroy().

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

  1. Εκτελέστε την εφαρμογή σας.
  2. Κάντε κλικ στην καρτέλα Logcat στο κάτω μέρος του Android Studio για να εμφανιστεί το παράθυρο Logcat. Θα πρέπει να δείτε τρία μηνύματα καταγραφής που δείχνουν τις τρεις καταστάσεις κύκλου ζωής στις οποίες έχει περάσει η Δραστηριότητα καθώς ξεκίνησε:
D/MainActivity: -------
D/MainActivity: onCreate
D/MainActivity: onStart
D/MainActivity: onResume

1.3 Εφαρμογή επανακλήσεων κύκλου ζωής στο SecondActivity

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

  1. Ανοίξτε το SecondActivity.
  2. Στην κορυφή της τάξης, προσθέστε μια σταθερά για τη μεταβλητή LOG_TAG:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
  1. Προσθέστε τις επανακλήσεις κύκλου ζωής και τις δηλώσεις καταγραφής στη δεύτερη Δραστηριότητα. (Μπορείτε να αντιγράψετε και να επικολλήσετε τις μεθόδους επανάκλησης από το MainActivity.)
  2. Προσθέστε μια δήλωση καταγραφής στη μέθοδο returnReply() λίγο πριν από τη μέθοδο finish():
Log.d(LOG_TAG, "End SecondActivity");

1.4 Παρατηρήστε το αρχείο καταγραφής καθώς εκτελείται η εφαρμογή**

  1. Εκτελέστε την εφαρμογή σας.
  2. Κάντε κλικ στην καρτέλα Logcat στο κάτω μέρος του Android Studio για να εμφανιστεί το παράθυρο Logcat.
  3. Εισαγάγετε Δραστηριότητα στο πλαίσιο αναζήτησης. Το Android logcat μπορεί να είναι πολύ μακρύ και ακατάστατο. Επειδή η μεταβλητή LOG_TAG σε κάθε τάξη περιέχει είτε τις λέξεις MainActivity είτε SecondActivity, αυτή η λέξη-κλειδί σάς επιτρέπει να φιλτράρετε το αρχείο καταγραφής μόνο για τα πράγματα που σας ενδιαφέρουν.

Διπλό πρόβλημα

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

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

ΣΥΜΒΟΥΛΗ: Εάν εκτελείτε την εφαρμογή σας σε εξομοιωτή, μπορείτε να προσομοιώσετε την περιστροφή με το Control+F11 ή το Control+Function+F11.

Κωδικός λύσης εργασίας 1

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

Κύρια Δραστηριότητα

Τα παρακάτω αποσπάσματα κώδικα εμφανίζουν τον προστιθέμενο κώδικα στο MainActivity, αλλά όχι ολόκληρη την κλάση.

Η μέθοδος onCreate():

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

        // Log the start of the onCreate() method.
        Log.d(LOG_TAG, "-------");
        Log.d(LOG_TAG, "onCreate");

        // Initialize all the view variables.
        mMessageEditText = findViewById(R.id.editText_main);
        mReplyHeadTextView = findViewById(R.id.text_header_reply);
        mReplyTextView = findViewById(R.id.text_message_reply);
}

Οι άλλες μέθοδοι κύκλου ζωής:

@Override
protected void onStart() {
        super.onStart();
        Log.d(LOG_TAG, "onStart");
}

@Override
protected void onPause() {
        super.onPause();
        Log.d(LOG_TAG, "onPause");
}

@Override
protected void onRestart() {
        super.onRestart();
        Log.d(LOG_TAG, "onRestart");
}

@Override
protected void onResume() {
        super.onResume();
        Log.d(LOG_TAG, "onResume");
}

@Override
protected void onStop() {
        super.onStop();
        Log.d(LOG_TAG, "onStop");
}

@Override
protected void onDestroy() {
        super.onDestroy();
        Log.d(LOG_TAG, "onDestroy");
}

Δεύτερη Δραστηριότητα

Τα παρακάτω αποσπάσματα κώδικα εμφανίζουν τον προστιθέμενο κώδικα στο SecondActivity, αλλά όχι ολόκληρη την κλάση.

Στην κορυφή της τάξης SecondActivity:

private static final String LOG_TAG = SecondActivity.class.getSimpleName();

Η μέθοδος returnReply():

public void returnReply(View view) {
        String reply = mReply.getText().toString();
        Intent replyIntent = new Intent();
        replyIntent.putExtra(EXTRA_REPLY, reply);
        setResult(RESULT_OK, replyIntent);
        Log.d(LOG_TAG, "End SecondActivity");
        finish();
}

Οι άλλες μέθοδοι κύκλου ζωής:

Το ίδιο με το MainActivity, παραπάνω.

4. 4. Εργασία 2: Αποθήκευση και επαναφορά της κατάστασης παρουσίας δραστηριότητας

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

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

Η κατάσταση κάθε Δραστηριότητας αποθηκεύεται ως ένα σύνολο ζευγών κλειδιών/τιμών σε ένα αντικείμενο Bundle που ονομάζεται κατάσταση παρουσίας δραστηριότητας. Το σύστημα αποθηκεύει τις πληροφορίες προεπιλεγμένης κατάστασης στη δέσμη κατάστασης παρουσίασης ακριβώς πριν από τη διακοπή της Δραστηριότητας και μεταβιβάζει αυτήν τη δέσμη στη νέα παρουσία δραστηριότητας για επαναφορά.

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

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

2.1 Αποθηκεύστε την κατάσταση παρουσίας δραστηριότητας με την onSaveInstanceState()

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

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

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

Σε αυτήν την εργασία προσθέτετε κώδικα για να διατηρήσετε την κατάσταση παρουσίας αυτών των δύο στοιχείων TextView χρησιμοποιώντας την onSaveInstanceState().

  1. Ανοίξτε το MainActivity.
  2. Προσθέστε αυτήν την υλοποίηση του σκελετού της onSaveInstanceState() στη Δραστηριότητα ή χρησιμοποιήστε Code > Override Methods για να εισαγάγετε μια παράκαμψη σκελετού.
@Override
public void onSaveInstanceState(Bundle outState) {
          super.onSaveInstanceState(outState);
}
  1. Ελέγξτε εάν η κεφαλίδα είναι ορατή αυτήν τη στιγμή και, αν ναι, βάλτε αυτήν την κατάσταση ορατότητας στο Bundle κατάστασης με τη μέθοδο putBoolean() και το κλειδί "reply_visible".
 if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
        outState.putBoolean("reply_visible", true);
    }

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

  1. Μέσα σε αυτόν τον ίδιο έλεγχο, προσθέστε το κείμενο της απάντησης στη δέσμη.
outState.putString("reply_text",mReplyTextView.getText().toString());

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

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

Σημειώστε ότι το σύστημα θα αποθηκεύσει την κατάσταση ορισμένων στοιχείων Προβολής, όπως τα περιεχόμενα του EditText.

2.2 Επαναφέρετε την κατάσταση παρουσίας δραστηριότητας στο onCreate()

Αφού αποθηκεύσετε την κατάσταση της παρουσίας Δραστηριότητας, θα πρέπει επίσης να την επαναφέρετε όταν η Δραστηριότητα αναδημιουργηθεί. Μπορείτε να το κάνετε αυτό είτε στην onCreate(), είτε υλοποιώντας την επανάκληση onRestoreInstanceState(), η οποία καλείται μετά την onStart() μετά τη δημιουργία της Δραστηριότητας.

Τις περισσότερες φορές, το καλύτερο μέρος για την επαναφορά της κατάστασης Δραστηριότητας είναι η onCreate(), για να διασφαλιστεί ότι η διεπαφή χρήστη, συμπεριλαμβανομένης της κατάστασης, είναι διαθέσιμη το συντομότερο δυνατό. Μερικές φορές είναι βολικό να το κάνετε στο onRestoreInstanceState() αφού έχει ολοκληρωθεί όλη η προετοιμασία ή να επιτρέψετε στις υποκλάσεις να αποφασίσουν εάν θα χρησιμοποιήσουν την προεπιλεγμένη εφαρμογή σας.

  1. Στη μέθοδο onCreate(), αφού αρχικοποιηθούν οι μεταβλητές View με findViewById(), προσθέστε μια δοκιμή για να βεβαιωθείτε ότι το savedInstanceState δεν είναι null.
// Initialize all the view variables.
mMessageEditText = findViewById(R.id.editText_main);
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);

// Restore the state.
if (savedInstanceState != null) {
}

Όταν δημιουργείται η δραστηριότητά σας, το σύστημα μεταβιβάζει την κατάσταση Bundle στην onCreate() ως το μοναδικό όρισμα. Την πρώτη φορά που καλείται η onCreate() και ξεκινά η εφαρμογή σας, το Bundle είναι null—δεν υπάρχει κατάσταση την πρώτη φορά που ξεκινά η εφαρμογή σας. Οι επόμενες κλήσεις στην onCreate() έχουν μια δέσμη γεμάτη με τα δεδομένα που αποθηκεύσατε στο onSaveInstanceState().

  1. Μέσα σε αυτόν τον έλεγχο, αφαιρέστε την τρέχουσα ορατότητα (αληθής ή ψευδής) από το Πακέτο με το κλειδί "reply_visible".
if (savedInstanceState != null) {
    boolean isVisible = 
                     savedInstanceState.getBoolean("reply_visible");
}
  1. Προσθέστε μια δοκιμή κάτω από αυτήν την προηγούμενη γραμμή για τη μεταβλητή isVisible.
if (isVisible) {
}

Εάν υπάρχει ένα κλειδί reply_visible στη δέσμη κατάστασης (και επομένως είναι αληθές το isVisible), θα χρειαστεί να επαναφέρετε την κατάσταση.

  1. Μέσα στη δοκιμή isVisible, κάντε ορατή την κεφαλίδα.
mReplyHeadTextView.setVisibility(View.VISIBLE);
  1. Λάβετε το μήνυμα απάντησης κειμένου από το Πακέτο με το κλειδί "reply_text" και ρυθμίστε την απάντηση TextView να εμφανίζει αυτήν τη συμβολοσειρά.
mReplyTextView.setText(savedInstanceState.getString("reply_text"));
  1. Κάντε επίσης ορατή την απάντηση TextView:
mReplyTextView.setVisibility(View.VISIBLE);
  1. Εκτελέστε την εφαρμογή. Δοκιμάστε να περιστρέψετε τη συσκευή ή τον εξομοιωτή για να βεβαιωθείτε ότι το μήνυμα απάντησης (αν υπάρχει) παραμένει στην οθόνη μετά την εκ νέου δημιουργία της Δραστηριότητας.

Κωδικός λύσης Εργασίας 2

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

Κύρια Δραστηριότητα

Τα παρακάτω αποσπάσματα κώδικα εμφανίζουν τον προστιθέμενο κώδικα στο MainActivity, αλλά όχι ολόκληρη την κλάση.

Η μέθοδος onSaveInstanceState():

@Override
public void onSaveInstanceState(Bundle outState) {
   super.onSaveInstanceState(outState);
   // If the heading is visible, message needs to be saved.
   // Otherwise we're still using default layout.
   if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
       outState.putBoolean("reply_visible", true);
       outState.putString("reply_text", 
                      mReplyTextView.getText().toString());
   }
}

Η μέθοδος onCreate():

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

   Log.d(LOG_TAG, "-------");
   Log.d(LOG_TAG, "onCreate");

   // Initialize all the view variables.
   mMessageEditText = findViewById(R.id.editText_main);
   mReplyHeadTextView = findViewById(R.id.text_header_reply);
   mReplyTextView = findViewById(R.id.text_message_reply);

   // Restore the saved state. 
   // See onSaveInstanceState() for what gets saved.
   if (savedInstanceState != null) {
       boolean isVisible = 
                     savedInstanceState.getBoolean("reply_visible");
       // Show both the header and the message views. If isVisible is
       // false or missing from the bundle, use the default layout.
       if (isVisible) {
           mReplyHeadTextView.setVisibility(View.VISIBLE);
           mReplyTextView.setText(savedInstanceState
                                  .getString("reply_text"));
           mReplyTextView.setVisibility(View.VISIBLE);
       }
   }
}

Το πλήρες έργο:

Android Studio Project: TwoActivitiesLifecycle

5. Κωδικοποίηση

Πρόκληση: Δημιουργήστε μια απλή εφαρμογή λίστας αγορών με μια κύρια δραστηριότητα για τη λίστα που δημιουργεί ο χρήστης και μια δεύτερη δραστηριότητα για μια λίστα με κοινά είδη αγορών.

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

Χρησιμοποιήστε ένα Intent για να μεταβιβάσετε πληροφορίες από μια δραστηριότητα σε άλλη. Βεβαιωθείτε ότι η τρέχουσα κατάσταση της λίστας αγορών αποθηκεύεται όταν ο χρήστης περιστρέφει τη συσκευή.

6. Περίληψη

  • Ο κύκλος ζωής της Δραστηριότητας είναι ένα σύνολο καταστάσεων στις οποίες η Δραστηριότητα μεταναστεύει, ξεκινώντας από την πρώτη δημιουργία και τελειώνοντας όταν το σύστημα Android ανακτήσει τους πόρους για αυτήν τη Δραστηριότητα.
  • Καθώς ο χρήστης πλοηγείται από τη μια Δραστηριότητα στην άλλη και εντός και εκτός της εφαρμογής σας, κάθε Δραστηριότητα μετακινείται μεταξύ καταστάσεων στον κύκλο ζωής Δραστηριότητα.
  • Κάθε κατάσταση στον κύκλο ζωής Δραστηριότητα έχει μια αντίστοιχη μέθοδο επανάκλησης που μπορείτε να παρακάμψετε στην κλάση Δραστηριότητα.
  • Οι μέθοδοι κύκλου ζωής είναι onCreate(), onStart(), onPause(), onRestart(), onResume(), onStop(), onDestroy().
  • Η παράκαμψη μιας μεθόδου επιστροφής κλήσης κύκλου ζωής σάς επιτρέπει να προσθέσετε συμπεριφορά που εμφανίζεται όταν η Δραστηριότητά σας μεταβαίνει σε αυτήν την κατάσταση.
  • Μπορείτε να προσθέσετε μεθόδους παράκαμψης σκελετού στις τάξεις σας στο Android Studio με Code > Override.
  • Οι αλλαγές στη διαμόρφωση της συσκευής, όπως η περιστροφή, έχουν ως αποτέλεσμα η Δραστηριότητα να καταστραφεί και να αναδημιουργηθεί σαν να ήταν νέα.
  • Ένα τμήμα της κατάστασης Δραστηριότητα διατηρείται σε μια αλλαγή διαμόρφωσης, συμπεριλαμβανομένων των τρεχουσών τιμών των στοιχείων EditText. Για όλα τα άλλα δεδομένα, πρέπει να αποθηκεύσετε ρητά αυτά τα δεδομένα μόνοι σας.
  • Αποθήκευση κατάστασης παρουσίας δραστηριότητας στη μέθοδο onSaveInstanceState().
  • Τα δεδομένα κατάστασης παρουσίας αποθηκεύονται ως απλά ζεύγη κλειδιών/τιμών σε ένα Bundle. Χρησιμοποιήστε τις μεθόδους Πακέτο για να τοποθετήσετε δεδομένα και να επαναφέρετε δεδομένα από τη δέσμη.
  • Επαναφέρετε την κατάσταση παρουσίας στην onCreate(), που είναι ο προτιμώμενος τρόπος, ή στην onRestoreInstanceState(). Πίσω