Làm thế nào để sử dụng ví dụ onSavedInstanceState


110

Tôi bối rối khi nói đến việc lưu một trạng thái. Vì vậy, tôi biết điều đó onSaveInstanceState(Bundle)được gọi khi hoạt động sắp bị phá hủy. Nhưng làm thế nào để bạn lưu trữ thông tin của mình trong đó và đưa thông tin về trạng thái ban đầu onCreate(Bundle savedInstanceState)? Tôi không hiểu gói này sẽ khôi phục thông tin như thế nào. Sẽ rất hữu ích nếu ai đó có thể cung cấp một ví dụ. Hướng dẫn Dev không làm tốt công việc giải thích điều này.

public class Conversation extends Activity {
    private ProgressDialog progDialog;
    int typeBar;
    TextView text1;
    EditText edit;
    Button respond;
    private String name;
    private String textAtView;
    private String savedName;

    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);

        setContentView(R.layout.dorothydialog);
        text1 = (TextView)findViewById(R.id.dialog);
        edit = (EditText)findViewById(R.id.repsond);
        respond = (Button)findViewById(R.id.button01);

        if(savedInstanceState != null){
            savedInstanceState.get(savedName);
            text1.setText(savedName);
        }
        else{
            text1.setText("Hello! What is your name?");
            respond.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    name = edit.getText().toString();
                    text1.setText("Nice to meet you "+ name);
                }   
            });
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState){
        super.onSaveInstanceState(outState);
        outState.putString(savedName, name);
    }
}

text1.setText (saveInstanceState.getString (tên lưu));
Spidy

@Spidy Còn onBackpressed thì sao? Làm thế nào tôi sẽ phản ứng với điều này với gói?
tj walker

Bạn sẽ không. Khi người dùng nhấn nút quay lại. Hoạt động bị giết. Sử dụng cơ sở dữ liệu để lưu trữ dữ liệu vĩnh viễn. Sử dụng Gói để trả ứng dụng đã khởi động lại về trạng thái trước đó.
Spidy

Câu trả lời:


198

Đây Bundlelà nơi chứa tất cả thông tin bạn muốn lưu. Bạn sử dụng các hàm put * để chèn dữ liệu vào đó. Đây là danh sách ngắn (còn nhiều hơn nữa) các hàm đặt bạn có thể sử dụng để lưu trữ dữ liệu trong Bundle.

putString
putBoolean
putByte
putChar
putFloat
putLong
putShort
putParcelable (used for objects but they must implement Parcelable)

Trong onCreatechức năng của bạn , điều này Bundleđược giao lại cho chương trình. Cách tốt nhất để kiểm tra xem ứng dụng đang được tải lại hay khởi động lần đầu tiên là:

if (savedInstanceState != null) {
    // Then the application is being reloaded
}

Để lấy lại dữ liệu, hãy sử dụng các hàm get * giống như các hàm put *. Dữ liệu được lưu trữ dưới dạng một cặp tên-giá trị. Đây giống như một bản đồ băm. Bạn cung cấp khóa và giá trị, sau đó khi bạn muốn giá trị trở lại, bạn cung cấp khóa và hàm sẽ nhận giá trị. Đây là một ví dụ ngắn.

@Override
public void onSaveInstanceState(Bundle outState) {
   outState.putString("message", "This is my message to be reloaded");
   super.onSaveInstanceState(outState);
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (savedInstanceState != null) {
        String message = savedInstanceState.getString("message");
        Toast.makeText(this, message, Toast.LENGTH_LONG).show();
    }
}

Tin nhắn đã lưu của bạn sẽ được hiển thị trên màn hình. Hi vọng điêu nay co ich.


14
onSaveInstanceState () được gọi trước khi hoạt động của bạn bị tạm dừng. Vì vậy, bất kỳ thông tin mà nó cần sau khi nó có khả năng bị phá hủy có thể được lấy từ Bundle lưu
Diederik

@Spidy Tuyệt vời! Bạn chỉ thực sự làm cho tôi hiểu mọi thứ về một gói! vì vậy tôi đoán outState được chuyển trở lại gói đã lưuInstanceState? Chính xác?
tj walker

Vâng. Các outState Bundle được chuyển trở lại trong khi Bundle savedInstanceState
Spidy

1
@tj walker - Một nguồn tài nguyên tuyệt vời khác là sách tham khảo kỹ thuật. Pro Android 3 là một nguồn tài nguyên phong phú nhưng giá rẻ mà bạn có thể nhận được trên Amazon
Spidy

@Spidy Tôi đã đăng mã hoạt động của mình ở trên cho bạn xem. Có lẽ bạn có thể cho tôi biết nếu tôi đang lưu trạng thái của mình đúng như bạn đã đề xuất.
tj walker

34

Một lưu ý chính mà tất cả các nhà phát triển Android mới nên biết là mọi thông tin trong Widget (TextView, Buttons, v.v.) sẽ được Android tự động lưu giữ miễn là bạn gán một ID cho chúng. Vì vậy, điều đó có nghĩa là hầu hết trạng thái giao diện người dùng được xử lý mà không có vấn đề gì. Chỉ khi bạn cần lưu trữ dữ liệu khác thì điều này mới trở thành vấn đề.

Từ Tài liệu Android :

Công việc duy nhất mà bạn yêu cầu là cung cấp một ID duy nhất (với thuộc tính android: id) cho mỗi widget mà bạn muốn lưu trạng thái của nó. Nếu một widget không có ID, thì nó không thể lưu trạng thái của nó


1
Đó có thực sự là sự thật? Bởi vì tôi có một hoạt động với một nút textview và chỉnh sửa văn bản. Nếu ứng dụng bị hủy hoặc bị giết, mọi thứ sẽ trở lại trạng thái ban đầu. Trong ứng dụng của tôi, văn bản textView thay đổi mỗi khi người dùng bấm nút.
tj walker

Có phải tài liệu không chính xác? Tôi chưa bao giờ có Chế độ xem lưu thông tin riêng của nó. Đặt cược tốt nhất của bạn là tự lưu tất cả thông tin của bạn theo ý kiến ​​của tôi.
Spidy

2
Nếu mục tiêu của bạn là lưu thông tin trênSaveInstanceState KHÔNG phải là nơi để làm điều đó. Đó là bởi vì không có gì đảm bảo rằng nó sẽ được gọi (xem tài liệu). Thay vào đó, bạn nên ghi vào cơ sở dữ liệu, SharedPreferences, v.v. Có, thông tin này là chính xác. Cách tốt nhất để kiểm tra xem giao diện người dùng của bạn có tồn tại theo kiểu này hay không là xoay màn hình của bạn khi các thay đổi về hướng sẽ chạy lại onCreate của bạn và sử dụng gói để khôi phục trạng thái.
Keith Adler

@Nissan Fan, bạn có thể cho một ví dụ như spidy đã làm ở trên không? Với các sharedprefs và tất cả? Cảm ơn
tj walker

Các ví dụ tốt nhất khá thẳng thắn đến từ tài liệu. developer.android.com/guide/topics/data/data-storage.html#pref
Keith Adler

6

Một thông tin tốt: bạn không cần phải kiểm tra xem đối tượng Bundle có bị rỗng trong phương thức onCreate () hay không. Sử dụng phương thức onRestoreInstanceState () mà hệ thống gọi sau phương thức onStart (). Hệ thống chỉ gọi onRestoreInstanceState () khi có trạng thái đã lưu để khôi phục, vì vậy bạn không cần phải kiểm tra xem Gói có rỗng không


5

Lưu trữ thông tin:

static final String PLAYER_SCORE = "playerScore";
static final String PLAYER_LEVEL = "playerLevel";

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Save the user's current game state
    savedInstanceState.putInt(PLAYER_SCORE, mCurrentScore);
    savedInstanceState.putInt(PLAYER_LEVEL, mCurrentLevel);

// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}

Nếu bạn không muốn khôi phục thông tin trong onCreate-Method của mình:

Dưới đây là các ví dụ: Tạo lại một Hoạt động

Thay vì khôi phục trạng thái trong onCreate (), bạn có thể chọn triển khai onRestoreInstanceState (), mà hệ thống gọi sau phương thức onStart (). Hệ thống chỉ gọi onRestoreInstanceState () khi có trạng thái đã lưu để khôi phục, vì vậy bạn không cần phải kiểm tra xem Gói có rỗng không

public void onRestoreInstanceState(Bundle savedInstanceState) {
// Always call the superclass so it can restore the view hierarchy
super.onRestoreInstanceState(savedInstanceState);

// Restore state members from saved instance
mCurrentScore = savedInstanceState.getInt(PLAYER_SCORE);
mCurrentLevel = savedInstanceState.getInt(PLAYER_LEVEL);
}

0

Về cơ bản onSaveInstanceState (Bundle outBundle) sẽ cung cấp cho bạn một gói. Khi bạn nhìn vào lớp Bundle, bạn sẽ thấy rằng bạn có thể đặt rất nhiều thứ khác nhau bên trong nó. Ở lần gọi tiếp theo của onCreate (), bạn chỉ lấy lại Gói đó làm đối số. Sau đó, bạn có thể đọc lại các giá trị của mình và khôi phục hoạt động của mình.

Giả sử bạn có một hoạt động với EditText. Người dùng đã viết một số văn bản bên trong nó. Sau đó, hệ thống sẽ gọi onSaveInstanceState () của bạn. Bạn đọc văn bản từ EditText và ghi nó vào Bundle thông qua Bundle.putString ("edit_text_value", theValue).

Bây giờ onCreate được gọi. Bạn kiểm tra xem gói được cung cấp có rỗng không. Nếu đúng như vậy, bạn có thể khôi phục giá trị của mình qua Bundle.getString ("edit_text_value") và đưa nó trở lại EditText của bạn.


0

Đây là để biết thêm thông tin.

Hãy tưởng tượng viễn cảnh này

  1. ActivityA khởi chạy ActivityB.
  2. ActivityB ra mắt ActivityAPrime mới bởi

    Intent intent = new Intent(getApplicationContext(), ActivityA.class);
    startActivity(intent);
    
  3. ActivityAPrime không có mối quan hệ nào với ActivityA.
    Trong trường hợp này, Gói trong ActivityAPrime.onCreate () sẽ không có giá trị.

Nếu ActivityA và ActivityAPrime phải là cùng một hoạt động thay vì các hoạt động khác nhau, thì ActivityB nên gọi finish () hơn là sử dụng startActivity ().


chỉ để làm rõ, trong ví dụ của bạn, ActivityA == ActivityA instance 1 và ActivityAPrime == ActivityA instance 2? ngoài ra, khi bạn nói, "ActivityB nên gọi finish () hơn là sử dụng startActivity ()." ý bạn là: (1) AcitivityB nên gọi finish () và sau đó sử dụng startActivity () sau đó (2) hoặc ActivityB nên gọi finish () chứ không phải sử dụng startActivity ()? nếu ý bạn là tùy chọn 2, bạn sẽ đề xuất ai đó khởi động lại cùng một hoạt động A instance1 như vậy để bạn có thể tải dữ liệu hoạt động chứa trước khi bị hủy / kết thúc? Cảm ơn
cjayem13

ActivityA và ActivityAPrime thuộc cùng một lớp nhưng các trường hợp khác nhau. Trong trường hợp này, ActivityA vẫn chưa kết thúc hoạt động kinh doanh của mình, ở giữa nó, nó đã tạo và bắt đầu ActivityB, vì vậy khi ActivityB kết thúc, ActivityA sẽ tiếp tục hoạt động kinh doanh còn lại của mình. Việc gọi startActivity trong trường hợp này là sai và mong đợi ActivityA và ActiviyAPrime là cùng một phiên bản. vì vậy chúng ta không nên khởi động lại ActivityA, chỉ cần kết thúc ActivityB và để ActivityA tiếp tục hoạt động của nó ...
ken

0

Nếu dữ liệu không được tải từ savedInstanceStatesử dụng mã sau.
Vấn đề là cuộc gọi url không hoàn thành đầy đủ, vì vậy hãy kiểm tra xem dữ liệu đã được tải chưa sau đó mới hiển thị giá trị instanceState.

//suppose data is not Loaded to savedInstanceState at 1st swipe
if (savedInstanceState == null && !mAlreadyLoaded){
    mAlreadyLoaded = true;
    GetStoryData();//Url Call
} else {
    if (listArray != null) {  //Data Array From JsonArray(ListArray)
        System.out.println("LocalData  " + listArray);
        view.findViewById(R.id.progressBar).setVisibility(View.GONE);
    }else{
        GetStoryData();//Url Call
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.