Câu hỏi Lưu trạng thái Hoạt động Android bằng cách sử dụng Trạng thái lưu trạng thái


Tôi đã làm việc trên nền tảng SDK Android và không rõ cách lưu trạng thái của ứng dụng. Vì vậy, cho công cụ tái tạo nhỏ này của ví dụ 'Hello, Android':

package com.android.hello;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class HelloAndroid extends Activity {

  private TextView mTextView = null;

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mTextView = new TextView(this);

    if (savedInstanceState == null) {
       mTextView.setText("Welcome to HelloAndroid!");
    } else {
       mTextView.setText("Welcome back.");
    }

    setContentView(mTextView);
  }
}

Tôi nghĩ rằng nó sẽ là đủ cho trường hợp đơn giản nhất, nhưng nó luôn luôn đáp ứng với thông điệp đầu tiên, không có vấn đề làm thế nào tôi di chuyển ra khỏi ứng dụng.

Tôi chắc rằng giải pháp đơn giản như ghi đè onPause hoặc một cái gì đó như thế, nhưng tôi đã bỏ đi trong tài liệu trong 30 phút hoặc lâu hơn và không tìm thấy bất cứ điều gì rõ ràng.


2238
2017-09-30 04:41


gốc


Khi được lưuInstanceState == null và khi nào nó không phải là null? - Trojan.ZBOT
Bạn đang phá hủy rõ ràng hoạt động của mình bằng cách - như bạn đã nói, điều hướng khỏi hoạt động đó, chẳng hạn như bằng cách nhấn lại. Trên thực tế, kịch bản trong đó 'savedInstanceState' này được sử dụng, là khi Android phá hủy hoạt động của bạn để giải trí. Đối với ý định: Nếu bạn thay đổi ngôn ngữ của điện thoại trong khi hoạt động đang chạy (và do đó cần phải tải các tài nguyên khác nhau từ dự án của bạn). Một trường hợp rất phổ biến khác là khi bạn xoay điện thoại sang một bên để hoạt động được tạo lại và hiển thị theo chiều ngang. - villoren
Để nhận được thông báo thứ hai, hãy bật "Không giữ hoạt động" trong tùy chọn dev. Nhấn nút trang chủ và quay lại từ các lần gần đây. - Yaroslav Mytkalyk
điều này khá hữu ích developer.android.com/training/basics/activity-lifecycle/… - Syed Raza Mehdi
bạn có thể làm điều đó với: onSaveInstanceState (Bundle savedInstanceState) - HPbyP


Các câu trả lời:


Bạn cần ghi đè onSaveInstanceState(Bundle savedInstanceState) và viết các giá trị trạng thái ứng dụng bạn muốn thay đổi thành Bundle tham số như thế này:

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
  super.onSaveInstanceState(savedInstanceState);
  // Save UI state changes to the savedInstanceState.
  // This bundle will be passed to onCreate if the process is
  // killed and restarted.
  savedInstanceState.putBoolean("MyBoolean", true);
  savedInstanceState.putDouble("myDouble", 1.9);
  savedInstanceState.putInt("MyInt", 1);
  savedInstanceState.putString("MyString", "Welcome back to Android");
  // etc.
}

Bundle về cơ bản là cách lưu trữ một bản đồ NVP ("Tên-Giá trị Cặp") và nó sẽ được chuyển vào onCreate() và cũng onRestoreInstanceState() nơi bạn muốn trích xuất các giá trị như thế này:

@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
  super.onRestoreInstanceState(savedInstanceState);
  // Restore UI state from the savedInstanceState.
  // This bundle has also been passed to onCreate.
  boolean myBoolean = savedInstanceState.getBoolean("MyBoolean");
  double myDouble = savedInstanceState.getDouble("myDouble");
  int myInt = savedInstanceState.getInt("MyInt");
  String myString = savedInstanceState.getString("MyString");
}

Bạn thường sử dụng kỹ thuật này để lưu trữ các giá trị cá thể cho ứng dụng của bạn (các lựa chọn, văn bản chưa được lưu, v.v.).


2275
2017-09-30 06:12



Bất kỳ cơ hội này hoạt động trên điện thoại, nhưng không phải trong giả lập? Tôi không thể có vẻ để có được một không lưu nullInstanceState. - Adam Jack
Tôi có một ArrayList của các điểm làm thế nào để lưu tất cả các điểm trong danh sách mảng này và sau đó khôi phục chúng? - AZ_
CẨN THẬN: bạn cần phải gọi super.onSaveInstanceState (savedInstanceState) trước khi thêm giá trị của bạn vào Bundle, hoặc họ sẽ bị xóa sổ trong cuộc gọi đó (Droid X Android 2.2). - jkschneider
Cẩn thận: các trạng thái tài liệu chính thức, rằng bạn nên lưu thông tin quan trọng trong onPause-Method vì phương thức onsaveinstance không phải là một phần của vòng đời của android. developer.android.com/reference/android/app/Activity.html - schlingel
Thực tế đó có hiệu quả onSaveInstanceState gần như vô dụng ngoại trừ trường hợp thay đổi hướng màn hình. Trong hầu hết các trường hợp khác, bạn không bao giờ có thể dựa vào nó và sẽ cần lưu trạng thái giao diện người dùng của mình ở nơi khác theo cách thủ công. Hoặc ngăn chặn ứng dụng của bạn bị giết bằng cách ghi đè hành vi nút BACK. Tôi không hiểu tại sao họ thậm chí còn thực hiện nó như thế này ngay từ đầu. Hoàn toàn không trực quan. Và bạn không thể có Bundle đó, hệ thống cung cấp cho bạn để lưu mọi thứ vào ngoại trừ trong phương pháp đặc biệt này. - chakrit


Các savedInstanceState chỉ dành cho trạng thái tiết kiệm được liên kết với một phiên bản hiện tại của một Hoạt động, ví dụ như điều hướng hiện tại hoặc thông tin lựa chọn, để nếu Android phá hủy và tạo lại một Activity, nó có thể trở lại như trước đây. Xem tài liệu cho onCreate và onSaveInstanceState

Đối với trạng thái sống lâu hơn, hãy xem xét sử dụng cơ sở dữ liệu SQLite, tệp hoặc tùy chọn. Xem Đang lưu trạng thái ổn định.


375
2017-09-30 05:03



Khi được lưuInstanceState == null và khi nào nó không phải là null? - Trojan.ZBOT
savedInstanceState là null khi hệ thống đang tạo một thể hiện mới của Activity của bạn và không null khi nó khôi phục. - Gabriel Câmara
... điều này đặt ra câu hỏi khi nào hệ thống có cần tạo một phiên bản Hoạt động mới không. Một số cách thoát khỏi ứng dụng không tạo ra một gói, do đó, một phiên bản mới phải được tạo. Đây là vấn đề cơ bản; nó có nghĩa là người ta không thể dựa vào về sự tồn tại của gói và phải thực hiện một số phương tiện lưu trữ liên tục thay thế. Lợi ích của onSave / onRestoreInstanceState là nó là một cơ chế mà hệ thống có thể làm đột ngộtmà không tốn nhiều tài nguyên hệ thống. Vì vậy, nó là tốt để hỗ trợ đó, cũng như có lưu trữ liên tục cho lối thoát duyên dáng hơn từ ứng dụng. - ToolmakerSteve


Lưu ý rằng nó là KHÔNG PHẢI An toàn để sử dụng onSaveInstanceState và onRestoreInstanceState  cho dữ liệu liên tục, theo tài liệu về trạng thái Hoạt động trong http://developer.android.com/reference/android/app/Activity.html.

Tài liệu nêu rõ (trong phần 'Vòng đời hoạt động'):

Lưu ý rằng điều quan trọng là phải lưu   dữ liệu liên tục trong onPause() thay thế   của onSaveInstanceState(Bundle)   bởi vì sau này không phải là một phần của   vòng đời gọi lại, do đó sẽ không   được gọi trong mọi tình huống như được mô tả   trong tài liệu của nó.

Nói cách khác, hãy lưu mã khôi phục / khôi phục của bạn cho dữ liệu liên tục trong onPause() và onResume()!

CHỈNH SỬA: Để làm rõ thêm, đây là onSaveInstanceState() tài liệu:

Phương pháp này được gọi trước khi một hoạt động có thể bị giết để khi nó   quay trở lại một thời gian trong tương lai nó có thể khôi phục lại trạng thái của nó. Dành cho   ví dụ, nếu hoạt động B được khởi chạy trước hoạt động A và tại một số   hoạt động điểm A bị giết để đòi lại tài nguyên, hoạt động A sẽ có   một cơ hội để lưu trạng thái hiện tại của giao diện người dùng của nó thông qua điều này   để khi người dùng quay trở lại hoạt động A, trạng thái của   giao diện người dùng có thể được khôi phục qua onCreate(Bundle) hoặc là    onRestoreInstanceState(Bundle).


366
2018-05-25 23:22



Chỉ cần để nitpick: nó không phải là không an toàn hoặc. Điều này chỉ phụ thuộc vào những gì bạn muốn bảo tồn và trong bao lâu, mà @Bernard không hoàn toàn rõ ràng về trong câu hỏi ban đầu của mình. InstanceState là hoàn hảo để giữ trạng thái UI hiện tại (dữ liệu được nhập vào các điều khiển, vị trí hiện tại trong danh sách vv), trong khi Pause / Resume là khả năng duy nhất để lưu trữ lâu dài. - Pontus Gagge
Điều này nên được downvoted. Nó không an toàn để sử dụng trên (Save | Restore) InstanceState như các phương pháp vòng đời (tức là làm bất cứ điều gì khác trong chúng hơn là lưu / khôi phục lại trạng thái). Chúng hoàn toàn tốt cho việc lưu / khôi phục trạng thái. Ngoài ra, bạn muốn lưu / khôi phục trạng thái trong onPause và onResume như thế nào? Bạn không nhận được Gói trong những phương pháp mà bạn có thể sử dụng, vì vậy bạn sẽ phải sử dụng một số tiết kiệm khác của nhà nước, trong cơ sở dữ liệu, tệp, v.v. đó là ngu ngốc. - Felix
Chúng tôi không nên bỏ phiếu cho người này ít nhất là ông đã nỗ lực để đi qua các tài liệu và tôi nghĩ rằng chúng tôi mọi người đang ở đây để thực sự xây dựng một cộng đồng hiểu biết và giúp đỡ lẫn nhau không DOWN VOTE. vì vậy 1 phiếu bầu cho nỗ lực này và tôi sẽ yêu cầu bạn không nên bỏ phiếu bầu thay vì bỏ phiếu hoặc bỏ phiếu .... người này rõ ràng là sự nhầm lẫn mà người ta muốn có khi trải qua tài liệu. 1 phiếu bầu :) - AZ_
Tôi không nghĩ rằng câu trả lời này xứng đáng là một downvote. Atleast anh đã cố gắng trả lời và trích dẫn một phần từ doco. - GSree
Câu trả lời này là hoàn toàn chính xác và xứng đáng UP bỏ phiếu, không xuống! Hãy để tôi làm rõ sự khác biệt giữa các tiểu bang cho những kẻ không nhìn thấy nó. Trạng thái GUI, giống như các nút radio được chọn và một số văn bản trong trường nhập, ít quan trọng hơn nhiều so với trạng thái dữ liệu, như các bản ghi được thêm vào danh sách được hiển thị trong một ListView. Sau này phải được lưu trữ vào cơ sở dữ liệu trong onPause vì đó là cuộc gọi được bảo đảm duy nhất. Nếu bạn đặt nó trong onSaveInstanceState thay vào đó, bạn có nguy cơ mất dữ liệu nếu không được gọi. Nhưng nếu lựa chọn nút radio không được lưu vì cùng một lý do - đó không phải là vấn đề lớn. - JBM


Đồng nghiệp của tôi đã viết một bài báo giải thích về Trạng thái Ứng dụng trên các thiết bị Android bao gồm các giải thích về Vòng đời Hoạt động và Thông tin Nhà nước, Cách lưu trữ Thông tin Nhà nước và tiết kiệm cho Nhà nước Bundle và SharedPreferences và hãy xem tại đây.

Bài viết bao gồm ba cách tiếp cận:

Lưu trữ dữ liệu kiểm soát giao thức / kiểm soát giao diện người dùng cục bộ cho thời gian sử dụng của ứng dụng (tức là tạm thời) bằng cách sử dụng Gói trạng thái cá thể

[Code sample – Store State in State Bundle]
@Override
public void onSaveInstanceState(Bundle savedInstanceState) 
{
  // Store UI state to the savedInstanceState.
  // This bundle will be passed to onCreate on next call.  EditText txtName = (EditText)findViewById(R.id.txtName);
  String strName = txtName.getText().toString();

  EditText txtEmail = (EditText)findViewById(R.id.txtEmail);
  String strEmail = txtEmail.getText().toString();

  CheckBox chkTandC = (CheckBox)findViewById(R.id.chkTandC);
  boolean blnTandC = chkTandC.isChecked();

  savedInstanceState.putString(“Name”, strName);
  savedInstanceState.putString(“Email”, strEmail);
  savedInstanceState.putBoolean(“TandC”, blnTandC);

  super.onSaveInstanceState(savedInstanceState);
}

Lưu trữ dữ liệu kiểm soát biến đổi / giao diện người dùng cục bộ giữa các cá thể ứng dụng (tức là vĩnh viễn) bằng cách sử dụng Tùy chọn được chia sẻ

[Code sample – Store State in SharedPreferences]
@Override
protected void onPause() 
{
  super.onPause();

  // Store values between instances here
  SharedPreferences preferences = getPreferences(MODE_PRIVATE);
  SharedPreferences.Editor editor = preferences.edit();  // Put the values from the UI
  EditText txtName = (EditText)findViewById(R.id.txtName);
  String strName = txtName.getText().toString();

  EditText txtEmail = (EditText)findViewById(R.id.txtEmail);
  String strEmail = txtEmail.getText().toString();

  CheckBox chkTandC = (CheckBox)findViewById(R.id.chkTandC);
  boolean blnTandC = chkTandC.isChecked();

  editor.putString(“Name”, strName); // value to store
  editor.putString(“Email”, strEmail); // value to store
  editor.putBoolean(“TandC”, blnTandC); // value to store    
  // Commit to storage
  editor.commit();
}

Giữ các cá thể đối tượng còn sống trong bộ nhớ giữa các hoạt động trong vòng đời của ứng dụng bằng cách sử dụng cá thể không cấu hình được giữ lại

[Code sample – store object instance]
private cMyClassType moInstanceOfAClass;// Store the instance of an object
@Override
public Object onRetainNonConfigurationInstance() 
{
  if (moInstanceOfAClass != null) // Check that the object exists
      return(moInstanceOfAClass);
  return super.onRetainNonConfigurationInstance();
}

171
2017-08-27 13:54



@ MartinBelcher-Eigo Bài viết nói về dữ liệu trong SharedPreferences rằng "Dữ liệu này được ghi vào cơ sở dữ liệu trên thiết bị .." Tôi tin rằng dữ liệu được lưu trữ trong một tệp trong thư mục của ứng dụng của hệ thống tệp. - Tom
Dữ liệu @Tom SharefPrefs được ghi vào tệp xml. Là xml một loại cơ sở dữ liệu? Tôi muốn nói nó là;) - MaciejGórski
Lưu ý rằng editor.apply() nhanh hơn editor.commit(). - Fred
Liên kết đã chết. - Sakiboy


Đây là một "bản ghi" cổ điển về phát triển Android. Có hai vấn đề ở đây:

  • Có một lỗi Android Framework tinh tế làm phức tạp rất nhiều việc quản lý ngăn xếp ứng dụng trong quá trình phát triển, ít nhất là trên các phiên bản cũ (không hoàn toàn chắc chắn nếu / khi nào / nó được sửa) như thế nào. Tôi sẽ thảo luận về lỗi này bên dưới.
  • Cách 'bình thường' hoặc dự định để quản lý vấn đề này là chính nó, khá phức tạp với tính hai mặt của onPause / onResume và onSaveInstanceState / onRestoreInstanceState

Duyệt qua tất cả các chủ đề này, tôi nghi ngờ rằng phần lớn thời gian các nhà phát triển đang nói về hai vấn đề khác nhau cùng một lúc ... do đó tất cả sự nhầm lẫn và báo cáo về "điều này không hiệu quả đối với tôi".

Đầu tiên, để làm rõ hành vi 'dự định': onSaveInstance và onRestoreInstance là mong manh và chỉ cho trạng thái thoáng qua. Mục đích sử dụng (afaict) là xử lý hoạt động giải trí khi điện thoại được xoay (thay đổi hướng). Nói cách khác, mục đích sử dụng là khi Hoạt động của bạn vẫn hợp lý 'trên đầu', nhưng vẫn phải được hệ thống khôi phục lại. Gói đã lưu không được duy trì bên ngoài quá trình / bộ nhớ / gc, vì vậy bạn không thể thực sự dựa vào điều này nếu hoạt động của bạn chuyển sang nền. Có, có lẽ bộ nhớ của Activity của bạn sẽ tồn tại trong chuyến đi của nó về phía sau và thoát khỏi GC, nhưng điều này không đáng tin cậy (cũng không thể dự đoán được).

Vì vậy, nếu bạn có một kịch bản mà có ý nghĩa 'tiến bộ người dùng' hoặc trạng thái cần được duy trì giữa 'khởi chạy' của ứng dụng của bạn, hướng dẫn là sử dụng onPause và onResume. Bạn phải tự chọn và chuẩn bị một cửa hàng liên tục.

NHƯNG - có một lỗi rất khó hiểu làm phức tạp tất cả điều này. Chi tiết có tại đây:

http://code.google.com/p/android/issues/detail?id=2373

http://code.google.com/p/android/issues/detail?id=5277

Về cơ bản, nếu ứng dụng của bạn được khởi chạy với cờ SingleTask, và sau đó bạn khởi động nó từ màn hình chính hoặc trình khởi chạy, sau đó lời gọi tiếp theo sẽ tạo một tác vụ MỚI ... bạn sẽ có hai phiên bản ứng dụng khác nhau sinh sống cùng một ngăn xếp ... rất lạ lùng rất nhanh. Điều này dường như xảy ra khi bạn khởi chạy ứng dụng của mình trong quá trình phát triển (tức là từ Eclipse hoặc Intellij), vì vậy các nhà phát triển chạy rất nhiều. Nhưng cũng thông qua một số cơ chế cập nhật cửa hàng ứng dụng (vì vậy nó cũng tác động đến người dùng của bạn).

Tôi đã chiến đấu qua các chủ đề này hàng giờ trước khi tôi nhận ra rằng vấn đề chính của tôi là lỗi này, chứ không phải là hành vi khung dự định. Đăng ký tuyệt vời và cách giải quyết (CẬP NHẬT: xem bên dưới) có vẻ là từ người dùng @kaciula trong câu trả lời này:

Trang chủ nhấn phím hành vi

CẬP NHẬT Tháng 6 năm 2013: Vài tháng sau, cuối cùng tôi đã tìm ra giải pháp 'đúng'. Bạn không cần phải quản lý bất kỳ cờ startApp stateful chính mình, bạn có thể phát hiện điều này từ khuôn khổ và bảo lãnh một cách thích hợp. Tôi sử dụng điều này gần đầu của LauncherActivity.onCreate của tôi:

if (!isTaskRoot()) {
    Intent intent = getIntent();
    String action = intent.getAction();
    if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && action != null && action.equals(Intent.ACTION_MAIN)) {
        finish();
        return;
    }
}

126
2017-10-19 23:47



Tại sao Android lại trở thành hệ điều hành di động lựa chọn thứ hai? chôn đầu trong tay - Nick Bauer


onSaveInstanceStateđược gọi khi hệ thống cần bộ nhớ và giết chết một ứng dụng. Nó không được gọi khi người dùng chỉ đóng ứng dụng. Vì vậy, tôi nghĩ rằng trạng thái ứng dụng cũng nên được lưu trong onPause Nó nên được lưu vào một số lưu trữ liên tục như Preferences hoặc là Sqlite


70
2018-05-07 00:21



Xin lỗi, điều đó không hoàn toàn chính xác. onSaveInstanceState được gọi trước khi hoạt động cần được thực hiện lại. tức là mỗi khi người dùng xoay thiết bị. Nó có nghĩa là để lưu trữ trạng thái xem thoáng qua. Khi android buộc ứng dụng đóng lại, onSaveInstanceState thực sự KHÔNG được gọi (đó là lý do tại sao nó không an toàn để lưu trữ dữ liệu ứng dụng quan trọng). onPause, tuy nhiên được bảo đảm được gọi trước khi hoạt động bị giết, vì vậy nó nên được sử dụng để lưu trữ thông tin vĩnh viễn trong các tùy chọn hoặc Squlite. Câu trả lời đúng, lý do sai. - moveaway00
@ moveaway00 - Một phần không chính xác. Nếu hệ thống giết chết ứng dụng để khôi phục tài nguyên, làm gọi onSaveInstanceState. Từ developer.android.com/training/basics/activity-lifecycle/… - "Hệ thống cũng có thể phá hủy hoạt động của bạn ... hoạt động tiền cảnh đòi hỏi nhiều tài nguyên hơn để hệ thống phải tắt các quá trình nền để khôi phục bộ nhớ. ... nếu hệ thống phá hủy hoạt động do ràng buộc hệ thống ... hệ thống ghi nhớ rằng nó tồn tại ... Dữ liệu đã lưu ... là tập hợp các cặp khóa-giá trị được lưu trữ trong một đối tượng Bundle. ". - ToolmakerSteve


Cả hai phương pháp đều hữu ích và hợp lệ và cả hai đều phù hợp nhất cho các kịch bản khác nhau:

  1. Người dùng chấm dứt ứng dụng và mở lại nó vào một ngày sau đó, nhưng ứng dụng cần tải lại dữ liệu từ phiên trước - điều này đòi hỏi một phương pháp lưu trữ liên tục như sử dụng SQLite.
  2. Người dùng chuyển đổi ứng dụng và sau đó quay trở lại bản gốc và muốn chọn nơi họ rời đi - lưu và khôi phục dữ liệu gói (chẳng hạn như dữ liệu trạng thái ứng dụng) trong onSaveInstanceState() và onRestoreInstanceState() thường là đủ.

Nếu bạn lưu dữ liệu trạng thái một cách liên tục, nó có thể được tải lại trong một onResume() hoặc là onCreate() (hoặc thực sự trên bất kỳ cuộc gọi vòng đời nào). Điều này có thể hoặc có thể không phải là hành vi mong muốn. Nếu bạn lưu trữ nó trong một gói trong một InstanceState, sau đó là tạm thời và chỉ phù hợp để lưu trữ dữ liệu để sử dụng trong cùng một phiên ‘người dùng’ (tôi sử dụng phiên hạn một cách lỏng lẻo) nhưng không phù hợp giữa ‘phiên’.

Nó không phải là một cách tiếp cận là tốt hơn so với khác, giống như tất cả mọi thứ, nó chỉ là quan trọng để hiểu những gì hành vi bạn yêu cầu và để lựa chọn phương pháp tiếp cận thích hợp nhất.


59
2018-06-27 16:17



Làm thế nào để chúng tôi lựa chọn giữa SQLite và Preferences khi tìm kiếm lưu trữ liên tục? - Deco


Tiết kiệm nhà nước là một kludge tốt nhất như xa như tôi đang quan tâm. Nếu bạn cần lưu dữ liệu liên tục, chỉ cần sử dụng SQLite cơ sở dữ liệu. Android làm cho nó SOOO dễ dàng.

Một cái gì đó như thế này:

import java.util.Date;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class dataHelper {

    private static final String DATABASE_NAME = "autoMate.db";
    private static final int DATABASE_VERSION = 1;

    private Context context;
    private SQLiteDatabase db;
    private OpenHelper oh ;

    public dataHelper(Context context) {
        this.context = context;
        this.oh = new OpenHelper(this.context);
        this.db = oh.getWritableDatabase();
    }

    public void close()
    {
        db.close();
        oh.close();
        db = null;
        oh = null;
        SQLiteDatabase.releaseMemory();
    }


    public void setCode(String codeName, Object codeValue, String codeDataType)
    {
        Cursor codeRow = db.rawQuery("SELECT * FROM code WHERE codeName = '"+  codeName + "'", null);
        String cv = "" ;

        if (codeDataType.toLowerCase().trim().equals("long") == true)
        {
            cv = String.valueOf(codeValue);
        }
        else if (codeDataType.toLowerCase().trim().equals("int") == true)
        {
            cv = String.valueOf(codeValue);
        }
        else if (codeDataType.toLowerCase().trim().equals("date") == true)
        {
            cv = String.valueOf(((Date)codeValue).getTime());
        }
        else if (codeDataType.toLowerCase().trim().equals("boolean") == true)
        {
            String.valueOf(codeValue);
        }
        else
        {
            cv = String.valueOf(codeValue);
        }

        if(codeRow.getCount() > 0) //exists-- update
        {
            db.execSQL("update code set codeValue = '" + cv +
                "' where codeName = '" + codeName + "'");
        }
        else // does not exist, insert
        {
            db.execSQL("INSERT INTO code (codeName, codeValue, codeDataType) VALUES(" +
                    "'" + codeName + "'," +
                    "'" + cv + "'," +
                    "'" + codeDataType + "')" );
        }
    }

    public Object getCode(String codeName, Object defaultValue)
    {
        //Check to see if it already exists
        String codeValue = "";
        String codeDataType = "";
        boolean found = false;
        Cursor codeRow  = db.rawQuery("SELECT * FROM code WHERE codeName = '"+  codeName + "'", null);
        if (codeRow.moveToFirst())
        {
            codeValue = codeRow.getString(codeRow.getColumnIndex("codeValue"));
            codeDataType = codeRow.getString(codeRow.getColumnIndex("codeDataType"));
            found = true;
        }

        if (found == false)
        {
            return defaultValue;
        }
        else if (codeDataType.toLowerCase().trim().equals("long") == true)
        {
            if (codeValue.equals("") == true)
            {
                return (long)0;
            }
            return Long.parseLong(codeValue);
        }
        else if (codeDataType.toLowerCase().trim().equals("int") == true)
        {
            if (codeValue.equals("") == true)
            {
                return (int)0;
            }
            return Integer.parseInt(codeValue);
        }
        else if (codeDataType.toLowerCase().trim().equals("date") == true)
        {
            if (codeValue.equals("") == true)
            {
                return null;
            }
            return new Date(Long.parseLong(codeValue));
        }
        else if (codeDataType.toLowerCase().trim().equals("boolean") == true)
        {
            if (codeValue.equals("") == true)
            {
                return false;
            }
            return Boolean.parseBoolean(codeValue);
        }
        else
        {
            return (String)codeValue;
        }
    }


    private static class OpenHelper extends SQLiteOpenHelper {

        OpenHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL("CREATE TABLE IF  NOT EXISTS code" +
            "(id INTEGER PRIMARY KEY, codeName TEXT, codeValue TEXT, codeDataType TEXT)");
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        }
    }
}

Một cuộc gọi đơn giản sau đó

dataHelper dh = new dataHelper(getBaseContext());
String status = (String) dh.getCode("appState", "safetyDisabled");
Date serviceStart = (Date) dh.getCode("serviceStartTime", null);
dh.close();
dh = null;

50
2018-06-23 17:07



Bởi vì phải mất quá nhiều thời gian để tải một cơ sở dữ liệu SQLite, xem xét rằng đây là trên đường dẫn quan trọng để hiển thị cho người dùng giao diện người dùng của ứng dụng. Tôi đã không thực sự hẹn giờ, vì vậy tôi rất vui được sửa chữa, nhưng chắc chắn tải và mở một tập tin cơ sở dữ liệu sẽ không được nhanh chóng? - Tom
Cảm ơn bạn rất nhiều vì đã cung cấp giải pháp mà một newbie có thể cắt và dán vào ứng dụng của họ và sử dụng ngay lập tức! @Tom Theo như tốc độ đi nó mất khoảng bảy giây để lưu trữ 1000 cặp, nhưng bạn có thể làm điều đó trong một AsyncTask. Tuy nhiên, bạn cần phải thêm {cursor.close ()} cuối cùng hoặc nó sẽ bị lỗi do rò rỉ bộ nhớ trong khi thực hiện việc này. - Noumenon
Tôi đã xem qua điều này và trong khi nó có vẻ gọn gàng Tôi đang do dự để thử sử dụng này trên Google Glass, đó là thiết bị tôi đang làm việc trên / với thời gian gần đây. - Stephen Tetreault


Tôi nghĩ tôi đã tìm ra câu trả lời. Hãy để tôi nói những gì tôi đã làm theo những từ đơn giản:

Giả sử tôi có hai hoạt động, activity1 và activity2 và tôi đang điều hướng từ activity1 đến activity2 (tôi đã thực hiện một số công việc trong activity2) và một lần nữa trở lại hoạt động 1 bằng cách nhấp vào một nút trong activity1. Bây giờ ở giai đoạn này tôi muốn trở lại hoạt động2 và tôi muốn xem hoạt động của mình2 trong cùng điều kiện khi tôi còn lại hoạt động2.

Đối với kịch bản trên, những gì tôi đã làm là trong tệp kê khai tôi đã thực hiện một số thay đổi như sau:

<activity android:name=".activity2"
          android:alwaysRetainTaskState="true"      
          android:launchMode="singleInstance">
</activity>

Và trong activity1 trên sự kiện click button, tôi đã làm như sau:

Intent intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
intent.setClassName(this,"com.mainscreen.activity2");
startActivity(intent);

Và trong activity2 trên sự kiện click button tôi đã làm như sau:

Intent intent=new Intent();
intent.setClassName(this,"com.mainscreen.activity1");
startActivity(intent);

Bây giờ điều gì sẽ xảy ra là bất kỳ thay đổi nào chúng ta đã thực hiện trong activity2 sẽ không bị mất, và chúng ta có thể xem activity2 trong cùng trạng thái như chúng ta đã để lại trước đó.

Tôi tin rằng đây là câu trả lời và điều này làm việc tốt cho tôi. Đúng nếu tôi đã sai lầm.


50
2018-02-05 11:35



@bagusflyer quan tâm cụ thể hơn ??? Nhận xét của bạn không hữu ích và không ai có thể giúp bạn dựa trên đó. - Stephen Tetreault
Đây là câu trả lời cho một tình huống khác: hai hoạt động trong cùng một ứng dụng. OP là về rời đi ứng dụng (ví dụ: nút trang chủ hoặc các phương tiện khác để chuyển sang một ứng dụng khác). - ToolmakerSteve