Làm thế nào để khai báo các biến toàn cầu trong Android?


595

Tôi đang tạo một ứng dụng yêu cầu đăng nhập. Tôi đã tạo ra hoạt động chính và đăng nhập.

Trong onCreatephương thức hoạt động chính tôi đã thêm điều kiện sau:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    ...

    loadSettings();
    if(strSessionString == null)
    {
        login();
    }
    ...
}

Các onActivityResultphương pháp được thực thi khi biểu mẫu đăng nhập chấm dứt trông như sau:

@Override
public void onActivityResult(int requestCode,
                             int resultCode,
                             Intent data)
{
    super.onActivityResult(requestCode, resultCode, data);
    switch(requestCode)
    {
        case(SHOW_SUBACTICITY_LOGIN):
        {
            if(resultCode == Activity.RESULT_OK)
            {

                strSessionString = data.getStringExtra(Login.SESSIONSTRING);
                connectionAvailable = true;
                strUsername = data.getStringExtra(Login.USERNAME);
            }
        }
    }

Vấn đề là hình thức đăng nhập đôi khi xuất hiện hai lần ( login()phương thức được gọi là hai lần) và cả khi bàn phím điện thoại trượt hình thức đăng nhập lại xuất hiện và tôi đoán vấn đề là biến strSessionString.

Có ai biết cách đặt biến toàn cục để tránh hình thức đăng nhập xuất hiện sau khi người dùng đã xác thực thành công không?


một hướng dẫn tốt về cách xử lý trạng thái hoạt động bằng cách sử dụng gói trạng thái đã lưu quicktips.in/,
Deepak Swami

Câu trả lời:


954

Tôi đã viết câu trả lời này vào năm '09 khi Android còn khá mới và có nhiều khu vực chưa được thiết lập tốt trong phát triển Android. Tôi đã thêm một phụ lục dài ở cuối bài này, giải quyết một số lời chỉ trích và nêu chi tiết về sự bất đồng về triết học mà tôi có với việc sử dụng Singletons thay vì phân loại Ứng dụng. Đọc nó có nguy cơ của riêng bạn.

TRẢ LỜI GỐC:

Vấn đề chung hơn mà bạn đang gặp phải là làm thế nào để lưu trạng thái qua một số Hoạt động và tất cả các phần trong ứng dụng của bạn. Một biến tĩnh (ví dụ, một singleton) là một cách phổ biến của Java để đạt được điều này. Tuy nhiên, tôi đã thấy rằng một cách thanh lịch hơn trong Android là liên kết trạng thái của bạn với bối cảnh Ứng dụng.

Như bạn đã biết, mỗi Hoạt động cũng là một Ngữ cảnh, là thông tin về môi trường thực thi của nó theo nghĩa rộng nhất. Ứng dụng của bạn cũng có ngữ cảnh và Android đảm bảo rằng nó sẽ tồn tại dưới dạng một thể hiện duy nhất trên ứng dụng của bạn.

Cách để làm điều này là tạo lớp con android.app.Application của riêng bạn , sau đó chỉ định lớp đó trong thẻ ứng dụng trong tệp kê khai của bạn. Bây giờ Android sẽ tự động tạo một thể hiện của lớp đó và làm cho nó có sẵn cho toàn bộ ứng dụng của bạn. Bạn có thể truy cập nó từ bất kỳ contextbằng cách sử dụng Context.getApplicationContext()phương thức ( Activitycũng cung cấp một phương thức getApplication()có hiệu quả chính xác tương tự). Sau đây là một ví dụ cực kỳ đơn giản, hãy cẩn thận:

class MyApp extends Application {

  private String myState;

  public String getState(){
    return myState;
  }
  public void setState(String s){
    myState = s;
  }
}

class Blah extends Activity {

  @Override
  public void onCreate(Bundle b){
    ...
    MyApp appState = ((MyApp)getApplicationContext());
    String state = appState.getState();
    ...
  }
}

Điều này về cơ bản có tác dụng tương tự như sử dụng biến tĩnh hoặc singleton, nhưng tích hợp khá tốt vào khung Android hiện có. Lưu ý rằng điều này sẽ không hoạt động trên các quy trình (nếu ứng dụng của bạn là một trong những quy trình hiếm hoi có nhiều quy trình).

Một vài điều cần lưu ý từ ví dụ trên; giả sử thay vào đó chúng ta đã làm một cái gì đó như:

class MyApp extends Application {

  private String myState = /* complicated and slow initialization */;

  public String getState(){
    return myState;
  }
}

Bây giờ việc khởi tạo chậm này (chẳng hạn như nhấn đĩa, nhấn mạng, chặn mọi thứ, v.v.) sẽ được thực hiện mỗi khi Ứng dụng được khởi tạo! Bạn có thể nghĩ rằng, đây chỉ là một lần cho quá trình và tôi sẽ phải trả chi phí dù sao, phải không? Ví dụ, như Dianne Hackborn đề cập dưới đây, hoàn toàn có thể quy trình của bạn được khởi tạo - điều chỉnh - để xử lý một sự kiện phát sóng nền. Nếu quá trình xử lý phát sóng của bạn không cần trạng thái này, bạn có khả năng chỉ cần thực hiện một loạt các hoạt động phức tạp và chậm chạp mà không có gì. Lười ngay lập tức là tên của trò chơi ở đây. Sau đây là cách sử dụng Ứng dụng phức tạp hơn một chút, điều này có ý nghĩa hơn đối với mọi thứ trừ cách sử dụng đơn giản nhất:

class MyApp extends Application {

  private MyStateManager myStateManager = new MyStateManager();

  public MyStateManager getStateManager(){
    return myStateManager ;
  }
}

class MyStateManager {

  MyStateManager() {
    /* this should be fast */
  }

  String getState() {
    /* if necessary, perform blocking calls here */
    /* make sure to deal with any multithreading/synchronicity issues */

    ...

    return state;
  }
}

class Blah extends Activity {

  @Override
  public void onCreate(Bundle b){
    ...
    MyStateManager stateManager = ((MyApp)getApplicationContext()).getStateManager();
    String state = stateManager.getState();
    ...
  }
}

Mặc dù tôi thích phân lớp ứng dụng hơn là sử dụng singletons ở đây như một giải pháp thanh lịch hơn, nhưng tôi muốn các nhà phát triển sử dụng singletons nếu thực sự cần thiết hơn là không suy nghĩ gì cả thông qua hiệu năng và đa luồng của trạng thái liên kết với lớp con Ứng dụng.

LƯU Ý 1: Cũng như nhận xét về an toàn, để buộc chính xác ghi đè Ứng dụng của bạn vào ứng dụng của bạn, một thẻ là cần thiết trong tệp kê khai. Một lần nữa, xem tài liệu Android để biết thêm. Một ví dụ:

<application
     android:name="my.application.MyApp" 
     android:icon="..."
     android:label="...">
</application>

CHÚ THÍCH 2: user608578 hỏi bên dưới cách thức này hoạt động với việc quản lý vòng đời đối tượng gốc. Tôi không theo kịp tốc độ sử dụng mã gốc với Android và tôi không đủ điều kiện để trả lời cách thức tương tác với giải pháp của mình. Nếu ai đó có câu trả lời cho điều này, tôi sẵn sàng ghi có cho họ và đưa thông tin vào bài đăng này để hiển thị tối đa.

ĐỊA CHỈ:

Như một số người đã lưu ý, đây không phải là một giải pháp cho trạng thái dai dẳng , có lẽ tôi nên nhấn mạnh nhiều hơn trong câu trả lời ban đầu. Tức là điều này không có nghĩa là một giải pháp để lưu người dùng hoặc thông tin khác có nghĩa là được duy trì trong suốt vòng đời của ứng dụng. Vì vậy, tôi cho rằng hầu hết những lời chỉ trích dưới đây liên quan đến Ứng dụng bị giết bất cứ lúc nào, v.v ..., vì vậy, mọi thứ cần được duy trì trên đĩa không nên được lưu trữ thông qua một lớp con Ứng dụng. Nó có nghĩa là một giải pháp để lưu trữ trạng thái ứng dụng tạm thời, có thể tạo lại dễ dàng (ví dụ người dùng đã đăng nhập) và các thành phần là một trường hợp duy nhất (ví dụ như trình quản lý mạng ứng dụng) ( KHÔNG phải là singleton!).

Dayerman đã rất tử tế khi chỉ ra một cuộc trò chuyện thú vị với Reto Meier và Dianne Hackborn, trong đó việc sử dụng các lớp con Ứng dụng không được khuyến khích trong các mẫu Singleton. Somatik cũng đã chỉ ra một cái gì đó thuộc về bản chất này sớm hơn, mặc dù lúc đó tôi không thấy nó. Do vai trò của Reto và Dianne trong việc duy trì nền tảng Android, tôi không thể thực sự khuyên bạn nên bỏ qua lời khuyên của họ. Những gì họ nói, đi. Tôi muốn không đồng ý với các ý kiến, bày tỏ liên quan đến việc thích Singleton hơn các lớp con Ứng dụng. Trong sự bất đồng của tôi, tôi sẽ sử dụng các khái niệm được giải thích tốt nhất trong phần giải thích StackExchange này về mẫu thiết kế Singleton, để tôi không phải xác định thuật ngữ trong câu trả lời này. Tôi rất khuyến khích lướt qua các liên kết trước khi tiếp tục. Từng điểm:

Dianne tuyên bố: "Không có lý do gì để phân lớp từ Ứng dụng. Không khác gì làm một đơn ..." Yêu cầu đầu tiên này không chính xác. Có hai lý do chính cho việc này. 1) Lớp Ứng dụng cung cấp bảo đảm trọn đời tốt hơn cho nhà phát triển ứng dụng; nó được đảm bảo có tuổi thọ của ứng dụng. Một singleton không bị ràng buộc chặt chẽ với thời gian tồn tại của ứng dụng (mặc dù nó có hiệu quả). Đây có thể không phải là vấn đề đối với nhà phát triển ứng dụng trung bình của bạn, nhưng tôi cho rằng đây chính xác là loại hợp đồng mà API Android sẽ cung cấp và nó cũng cung cấp sự linh hoạt hơn cho hệ thống Android, bằng cách giảm thiểu thời gian tồn tại của liên kết dữ liệu. 2) Lớp Ứng dụng cung cấp cho nhà phát triển ứng dụng một chủ sở hữu cá thể duy nhất cho trạng thái, đó là rất khác nhau từ một chủ sở hữu nhà nước Singleton. Để biết danh sách về sự khác biệt, xem liên kết giải thích Singleton ở trên.

Dianne tiếp tục, "... rất có thể sẽ là điều bạn hối tiếc trong tương lai khi bạn thấy đối tượng Ứng dụng của mình trở thành mớ hỗn độn lớn về những gì nên là logic ứng dụng độc lập." Điều này chắc chắn không phải là không chính xác, nhưng đây không phải là lý do để chọn Singleton trên lớp con Ứng dụng. Không có lý lẽ nào của Diane đưa ra lý do rằng sử dụng Singleton tốt hơn lớp con Ứng dụng, tất cả những gì cô ấy cố gắng thiết lập là việc sử dụng Singleton không tệ hơn lớp con Ứng dụng, điều mà tôi tin là sai.

Cô ấy tiếp tục, "Và điều này dẫn đến một cách tự nhiên hơn về cách bạn nên quản lý những thứ này - khởi tạo chúng theo yêu cầu." Điều này bỏ qua thực tế là không có lý do gì bạn không thể khởi tạo theo yêu cầu bằng cách sử dụng một lớp con Ứng dụng. Một lần nữa không có sự khác biệt.

Dianne kết thúc với "Bản thân khung này có hàng tấn tấn đơn cho tất cả các dữ liệu được chia sẻ nhỏ mà nó duy trì cho ứng dụng, chẳng hạn như bộ nhớ tài nguyên được tải, nhóm đối tượng, v.v. Nó hoạt động rất tốt." Tôi không tranh luận rằng sử dụng Singletons không thể hoạt động tốt hoặc không phải là một sự thay thế hợp pháp. Tôi cho rằng Singletons không cung cấp hợp đồng mạnh mẽ với hệ thống Android như sử dụng một lớp con Ứng dụng và hơn nữa việc sử dụng Singletons thường chỉ ra thiết kế không linh hoạt, không dễ sửa đổi và dẫn đến nhiều vấn đề. IMHO, hợp đồng mạnh mẽ mà API Android cung cấp cho các ứng dụng dành cho nhà phát triển là một trong những khía cạnh hấp dẫn và dễ chịu nhất của lập trình với Android, và đã giúp dẫn đến việc nhà phát triển sớm áp dụng nền tảng Android để đạt được thành công như ngày nay.

Dianne cũng đã bình luận bên dưới, đề cập đến một nhược điểm bổ sung cho việc sử dụng các lớp con Ứng dụng, họ có thể khuyến khích hoặc làm cho việc viết mã hiệu suất ít dễ dàng hơn. Điều này rất đúng và tôi đã chỉnh sửa câu trả lời này để nhấn mạnh tầm quan trọng của việc xem xét sự hoàn hảo ở đây và thực hiện phương pháp đúng nếu bạn đang sử dụng phân lớp Ứng dụng. Như Dianne tuyên bố, điều quan trọng cần nhớ là lớp Ứng dụng của bạn sẽ được khởi tạo mỗi khi quá trình của bạn được tải (có thể nhiều lần cùng một lúc nếu ứng dụng của bạn chạy trong nhiều quy trình!) Ngay cả khi quy trình chỉ được tải cho phát sóng nền biến cố. Do đó, điều quan trọng là sử dụng lớp Ứng dụng nhiều hơn như một kho lưu trữ con trỏ tới các thành phần được chia sẻ của ứng dụng của bạn chứ không phải là nơi để thực hiện bất kỳ xử lý nào!

Tôi để lại cho bạn danh sách các nhược điểm sau đối với Singletons, vì bị đánh cắp từ liên kết StackExchange trước đó:

  • Không có khả năng sử dụng các lớp trừu tượng hoặc giao diện;
  • Không có khả năng phân lớp;
  • Khớp nối cao trên ứng dụng (khó sửa đổi);
  • Khó kiểm tra (không thể giả / giả trong các bài kiểm tra đơn vị);
  • Khó song song trong trường hợp trạng thái đột biến (yêu cầu khóa mở rộng);

và thêm của riêng tôi:

  • Hợp đồng trọn đời không rõ ràng và không thể quản lý không được sử dụng cho phát triển Android (hoặc hầu hết khác);

93
Cảm ơn Soonil - những câu trả lời kiểu này là lý do tại sao tôi yêu Stack Overflow rất nhiều. BẠN ĐÃ LÀM RẤT TỐT!
JohnnyLambada

5
Đối với bất kỳ ai thắc mắc làm thế nào để "chỉ định lớp đó trong thẻ ứng dụng trong tệp kê khai của bạn", thì trong bài viết này, có hai câu trả lời khác cho câu hỏi này mô tả cách thực hiện (sử dụng android: name), một bởi ebuprofen và một của Mike Brown.
Tyler Collier

9
Ngay sau đó, câu trả lời của bạn là đúng, nhưng bạn có thể nhận thấy rằng chúng ta nên thêm <application android: name = ". MyApp" ... /> vào tệp Bản kê khai Android?
chống an toàn

12
Hãy để tôi nhắc lại một lần nữa, bạn không nên sử dụng Ứng dụng cho toàn cầu. Nó không có ích, không mang lại lợi ích nào cho singletons và có thể gây hại tích cực, chẳng hạn như làm tổn hại đến hiệu suất khởi chạy quy trình của bạn. Tại thời điểm Ứng dụng đang được tạo, bạn không biết quy trình của mình đang được tạo để làm gì. Bằng cách lười biếng khởi tạo singletons khi cần, bạn chỉ cần làm công việc cần thiết. Ví dụ: nếu quy trình của bạn đang được khởi chạy để xử lý một chương trình phát sóng về một số sự kiện nền, thì không có lý do gì để khởi tạo bất kỳ trạng thái toàn cầu nào mà UI của bạn cần.
hackbod

14
Ngoài ra, hãy thực sự rõ ràng ở đây - tất cả các lập luận của bạn chống lại những người độc thân là hoàn toàn hợp lệ, khi chúng ta đang nói về những tình huống mà bạn thực sự đang lựa chọn giữa một người độc thân và một cách tiếp cận khác không phải là toàn cầu; singletons là toàn cầu, với tất cả các cảnh báo về toàn cầu áp dụng. Tuy nhiên, Ứng dụng cũng là một singleton . Bạn không thoát khỏi những vấn đề đó bằng cách chuyển sang Ứng dụng phân lớp, Ứng dụng hoàn toàn giống như một đơn (nhưng tệ hơn), nó chỉ cho phép bạn tự lừa mình rằng bạn đang làm gì đó sạch sẽ hơn. Nhưng bạn không.
hackbod

153

Tạo lớp con này

public class MyApp extends Application {
  String foo;
}

Trong AndroidManifest.xml, thêm android: name

Thí dụ

<application android:name=".MyApp" 
       android:icon="@drawable/icon" 
       android:label="@string/app_name">

1
cảm ơn vì điều đó. Tôi đã tự hỏi làm thế nào để khai báo nó trong bảng kê khai
Ai đó ở đâu đó vào

3
Để nó hoạt động với tôi, tôi đã phải xóa "." trong ".MyApp"
Ai đó ở đâu đó vào

3
chỉ cần khai báo nó sau hoạt động chính, nếu không nó có thể không cài đặt / triển khai
sami

11
chỉ muốn nói, cái này có trong thẻ ứng dụng MAIN đã có sẵn ... đây không phải là cái thứ hai :) phải học một cách khó khăn.
bwoogie

java.lang.IllegalAccessException: access to class is not allowed
Raptor

142

Đề xuất của Soonil về cách giữ trạng thái cho ứng dụng là tốt, tuy nhiên nó có một điểm yếu - có những trường hợp khi HĐH giết chết toàn bộ quá trình ứng dụng. Dưới đây là tài liệu về điều này - Quy trình và vòng đời .

Hãy xem xét một trường hợp - ứng dụng của bạn đi vào nền vì có ai đó đang gọi cho bạn (Ứng dụng điện thoại hiện đang ở phía trước). Trong trường hợp này && trong một số điều kiện khác (kiểm tra liên kết ở trên để biết chúng có thể là gì), HĐH có thể giết quá trình ứng dụng của bạn, bao gồm cả thể hiện của Applicationlớp con. Kết quả là nhà nước bị mất. Khi bạn quay lại ứng dụng sau đó, thì HĐH sẽ khôi phục lại ngăn xếp hoạt động và thể hiện của Applicationlớp con, tuy nhiên myStatetrường sẽ là null.

AFAIK, cách duy nhất để đảm bảo an toàn trạng thái là sử dụng bất kỳ loại trạng thái nào tồn tại, ví dụ: sử dụng riêng tư cho tệp ứng dụng hoặc SharedPrefernces(cuối cùng sử dụng riêng tư cho tệp ứng dụng trong hệ thống tệp nội bộ).


10
+1 để duy trì với SharedPreferences; đây là cách tôi đã thấy nó được thực hiện Tôi thấy lạ khi lạm dụng hệ thống ưu tiên cho trạng thái đã lưu, nhưng nó hoạt động tốt đến mức vấn đề trở thành một câu hỏi về thuật ngữ.
Cheezmeister

1
bạn có thể vui lòng gửi mã (hoặc cung cấp một liên kết đến một lời giải thích) như cách thức SharedPreferences được sử dụng để giải quyết vấn đề mà Arhimed mô tả
Ai đó ở đâu đó vào

2
Tùy chọn, cơ sở dữ liệu, tuần tự hóa tệp, v.v. .
Darren Hinderer

1
Hành vi này rất khó chịu - sẽ không tệ lắm nếu phương thức onTerminate () của ứng dụng của bạn được gọi để bạn có thể xử lý tình huống một cách thanh lịch.
Dean Wild

2
Đây là câu trả lời đúng theo ý kiến ​​của tôi. Đó là một lỗi để dựa vào cùng một ứng dụng hiện có trong các hoạt động. Theo kinh nghiệm của tôi, Android khá phổ biến để phá bỏ hoàn toàn và tạo lại toàn bộ quá trình của bạn trong khi bạn làm nền. Làm nền có thể chỉ có nghĩa là khởi chạy một ý định máy ảnh, ý định trình duyệt hoặc nhận một cuộc gọi điện thoại.
Jared Kells

26

Chỉ là một ghi chú ..

thêm vào:

android:name=".Globals"

hoặc bất cứ điều gì bạn đặt tên lớp con của bạn vào thẻ hiện có <application> . Tôi tiếp tục cố gắng thêm một <application>thẻ khác vào bảng kê khai và sẽ có một ngoại lệ.


Xin chào, Gimbl. Tôi đã từng gặp vấn đề tương tự. Tôi cũng đã có thẻ <application> của riêng mình và khi tôi cố gắng thêm một thẻ <application> khác, tôi cũng gặp vấn đề tương tự như bạn (thông báo ngoại lệ). Nhưng tôi đã làm những gì bạn đề cập, và nó không hoạt động. Tôi thêm android: name = ". GlobalClass" vào thẻ <application> của tôi nhưng nó không hoạt động. Bạn có thể giải thích đầy đủ làm thế nào bạn giải quyết nó ??
Sonhja

3
Tốt <manifest> <application android: name = ". GlobalData"> </ application> </ manifest>. Xấu <manifest> <application> </ application> <application android: name = ". GlobalData"> </ application> </ manifest>
Gimbl

13

Tôi cũng không thể tìm cách chỉ định thẻ ứng dụng, nhưng sau rất nhiều Google, nó trở nên rõ ràng từ tài liệu tệp kê khai: sử dụng android: name, ngoài biểu tượng và nhãn mặc định trong khổ thơ ứng dụng.

android: name Tên đủ điều kiện của một lớp con Ứng dụng được triển khai cho ứng dụng. Khi quá trình ứng dụng được bắt đầu, lớp này được khởi tạo trước bất kỳ thành phần nào của ứng dụng.

Lớp con là tùy chọn; hầu hết các ứng dụng sẽ không cần. Trong trường hợp không có lớp con, Android sử dụng một thể hiện của lớp Ứng dụng cơ sở.


13

Điều gì về việc đảm bảo bộ sưu tập bộ nhớ riêng với các cấu trúc toàn cầu như vậy?

Các hoạt động có một onPause/onDestroy()phương thức được gọi là hủy diệt, nhưng lớp Ứng dụng không có tương đương. Cơ chế nào được khuyến nghị để đảm bảo rằng các cấu trúc toàn cầu (đặc biệt là các cấu trúc chứa tham chiếu đến bộ nhớ riêng) là rác được thu thập một cách thích hợp khi ứng dụng bị hủy hoặc ngăn xếp tác vụ được đặt trong nền?


1
Giải pháp rõ ràng là triển khai giao diện Đóng cho các đối tượng của bạn chịu trách nhiệm về tài nguyên bản địa và đảm bảo chúng được quản lý bằng câu lệnh thử với tài nguyên hoặc thứ gì khác. Trường hợp xấu nhất bạn luôn có thể sử dụng một bộ hoàn thiện đối tượng.
sớm

5

Chỉ cần bạn xác định một tên ứng dụng như dưới đây sẽ hoạt động:

<application
  android:name="ApplicationName" android:icon="@drawable/icon">
</application>

4

Giống như đã thảo luận ở trên, hệ điều hành có thể giết chết ỨNG DỤNG mà không có bất kỳ thông báo nào (không có sự kiện onDestroy) vì vậy không có cách nào để lưu các biến toàn cục này.

SharedPreferences có thể là một giải pháp NGOẠI TRỪ bạn có các biến CẤU CẤU CẤP (trong trường hợp của tôi, tôi có mảng số nguyên để lưu trữ ID mà người dùng đã xử lý). Vấn đề với SharedPreferences là rất khó để lưu trữ và truy xuất các cấu trúc này mỗi khi các giá trị cần thiết.

Trong trường hợp của tôi, tôi đã có một DỊCH VỤ nền để tôi có thể di chuyển các biến này đến đó và vì dịch vụ có sự kiện onDestroy, tôi có thể lưu các giá trị đó một cách dễ dàng.


onDestroy () không được bảo đảm để được gọi ngay cả đối với một dịch vụ.
Tìm hiểu OpenGL ES

Vâng, điều này có thể xảy ra nhưng chỉ trong trường hợp quan trọng.
Adorjan Princz

4

Nếu một số biến được lưu trữ trong sqlite và bạn phải sử dụng chúng trong hầu hết các hoạt động trong ứng dụng của mình. sau đó Ứng dụng có thể là cách tốt nhất để đạt được nó. Truy vấn các biến từ cơ sở dữ liệu khi ứng dụng bắt đầu và lưu trữ chúng trong một trường. Sau đó, bạn có thể sử dụng các biến này trong các hoạt động của bạn.

Vì vậy, tìm đúng cách, và không có cách tốt nhất.


3

Bạn có thể có một trường tĩnh để lưu trữ loại trạng thái này. Hoặc đặt nó vào Gói tài nguyên và khôi phục từ đó trên onCreate (Gói đã lưuInstanceState). Chỉ cần đảm bảo rằng bạn hoàn toàn hiểu vòng đời được quản lý ứng dụng Android (ví dụ: tại sao đăng nhập () được gọi khi thay đổi hướng bàn phím).


2

KHÔNG NÊN Sử dụng một <application>thẻ khác trong tệp kê khai. Chỉ cần thực hiện một thay đổi trong <application>thẻ hiện có , thêm dòng này vào android:name=".ApplicationName", ApplicationNamesẽ là tên của lớp con của bạn (sử dụng để lưu trữ toàn cầu) mà bạn sắp tạo.

vì vậy, cuối cùng thẻ MỘT VÀ CHỈ của bạn <application>trong tệp kê khai sẽ trông như thế này: -

<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.AppCompat.NoActionBar"
        android:name=".ApplicationName"
        >

1

bạn có thể sử dụng Ý định, Sqlite hoặc Tùy chọn chia sẻ. Khi nói đến lưu trữ phương tiện, như tài liệu, ảnh và video, bạn có thể tạo các tệp mới thay thế.


1

Bạn có thể làm điều này bằng hai cách tiếp cận:

  1. Sử dụng lớp Ứng dụng
  2. Sử dụng tùy chọn chia sẻ

  3. Sử dụng lớp Ứng dụng

Thí dụ:

class SessionManager extends Application{

  String sessionKey;

  setSessionKey(String key){
    this.sessionKey=key;
  }

  String getSessisonKey(){
    return this.sessionKey;
  }
}

Bạn có thể sử dụng lớp trên để thực hiện đăng nhập trong MainActivity của mình như bên dưới. Mã sẽ trông giống như thế này:

@override 
public void onCreate (Bundle savedInstanceState){
  // you will this key when first time login is successful.
  SessionManager session= (SessionManager)getApplicationContext();
  String key=getSessisonKey.getKey();
  //Use this key to identify whether session is alive or not.
}

Phương pháp này sẽ làm việc để lưu trữ tạm thời. Bạn thực sự không biết bất cứ điều gì khi hệ điều hành sẽ giết ứng dụng, vì bộ nhớ thấp. Khi ứng dụng của bạn ở chế độ nền và người dùng đang điều hướng qua ứng dụng khác cần nhiều bộ nhớ hơn để chạy, thì ứng dụng của bạn sẽ bị hủy do hệ điều hành được ưu tiên hơn cho các quy trình nền trước hơn nền. Do đó đối tượng ứng dụng của bạn sẽ là null trước khi người dùng đăng xuất. Do đó, tôi khuyên bạn nên sử dụng phương pháp thứ hai Được chỉ định ở trên.

  1. Sử dụng sở thích chung.

    String MYPREF="com.your.application.session"
    
    SharedPreferences pref= context.getSharedPreferences(MyPREF,MODE_PRIVATE);
    
    //Insert key as below:
    
    Editot editor= pref.edit();
    
    editor.putString("key","value");
    
    editor.commit();
    
    //Get key as below.
    
    SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
    
    String key= getResources().getString("key");

0

Về kết quả hoạt động được gọi trước khi tiếp tục. Vì vậy, di chuyển bạn kiểm tra đăng nhập để tiếp tục và đăng nhập thứ hai của bạn có thể bị chặn sau khi hoạt động secomd đã trả lại kết quả tích cực. Trên sơ yếu lý lịch được gọi mỗi lần vì vậy không phải lo lắng về việc nó không được gọi lần đầu tiên.


0

Cách tiếp cận của phân lớp cũng đã được sử dụng bởi khung BARACUS. Theo quan điểm của tôi, Ứng dụng phân lớp được dự định để hoạt động với vòng đời của Android; đây là điều mà bất kỳ Container ứng dụng nào cũng làm. Thay vì có toàn cầu sau đó, tôi đăng ký đậu vào bối cảnh này và cho phép chúng được đưa vào bất kỳ lớp nào có thể quản lý theo ngữ cảnh. Mỗi ví dụ đậu được tiêm thực sự là một singleton.

Xem ví dụ này để biết chi tiết

Tại sao làm việc thủ công nếu bạn có thể có nhiều hơn nữa?


0
class GlobaleVariableDemo extends Application {

    private String myGlobalState;

    public String getGlobalState(){
     return myGlobalState;
    }
    public void setGlobalState(String s){
     myGlobalState = s;
    }
}

class Demo extends Activity {

@Override
public void onCreate(Bundle b){
    ...
    GlobaleVariableDemo appState = ((GlobaleVariableDemo)getApplicationContext());
    String state = appState.getGlobalState();
    ...
    }
}

0

Bạn có thể tạo một lớp mở rộng Applicationlớp và sau đó khai báo biến của bạn là một trường của lớp đó và cung cấp phương thức getter cho nó.

public class MyApplication extends Application {
    private String str = "My String";

    synchronized public String getMyString {
        return str;
    }
}

Và sau đó để truy cập vào biến đó trong Hoạt động của bạn, hãy sử dụng:

MyApplication application = (MyApplication) getApplication();
String myVar = application.getMyString();
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.