Android: Làm cách nào để lấy chuỗi từ tài nguyên bằng tên của nó?


553

Tôi muốn có 2 ngôn ngữ cho UI và các giá trị chuỗi riêng biệt cho chúng trong tệp tài nguyên của mình res\values\strings.xml:

<string name="tab_Books_en">Books</string>
<string name="tab_Quotes_en">Quotes</string>
<string name="tab_Questions_en">Questions</string>
<string name="tab_Notes_en">Notes</string>
<string name="tab_Bookmarks_en">Bookmarks</string>

<string name="tab_Books_ru">Книги</string>
<string name="tab_Quotes_ru">Цитаты</string>
<string name="tab_Questions_ru">Вопросы</string>
<string name="tab_Notes_ru">Заметки</string>
<string name="tab_Bookmarks_ru">Закладки</string>

Bây giờ tôi cần lấy lại các giá trị này một cách linh hoạt trong ứng dụng của mình:

spec.setContent(R.id.tabPage1);
String pack = getPackageName();
String id = "tab_Books_" + Central.lang;
int i = Central.Res.getIdentifier(id, "string", pack);
String str = Central.Res.getString(i);

Vấn đề của tôi là vậy i = 0.

Tại sao nó không hoạt động trong trường hợp của tôi?


1
Bạn có chắc chắn rằng Central.lang là một trong hai enhoặc ru?
K-ballo

1
Cần thêm thông tin để kiểm tra mã của bạn. trạng thái của mỗi var trước khi nhận i là gì? Dù sao, bạn nên sử dụng hỗ trợ bản địa hóa mặc định trong Android để đơn giản hóa mọi thứ.
Alin

Câu trả lời:


1069

Liên kết mà bạn đang đề cập dường như hoạt động với các chuỗi được tạo khi chạy. Các chuỗi từ String.xml không được tạo trong thời gian chạy. Bạn có thể lấy chúng qua

String mystring = getResources().getString(R.string.mystring);

getResources()là một phương thức của Contextlớp. Nếu bạn ở trong một Activityhoặc một Service(mở rộng Bối cảnh), bạn có thể sử dụng nó như trong đoạn trích này.

Cũng lưu ý rằng toàn bộ sự phụ thuộc ngôn ngữ có thể được chăm sóc bởi khung công tác Android . Đơn giản chỉ cần tạo các thư mục khác nhau cho mỗi ngôn ngữ. Nếu tiếng Anh là ngôn ngữ mặc định của bạn, chỉ cần đặt các chuỗi tiếng Anh vào res/values/strings.xml. Sau đó tạo một thư mục mới values-ruvà đặt các chuỗi tiếng Nga có tên giống hệt vào res/values-ru/strings.xml. Từ thời điểm này, android chọn một cái đúng tùy thuộc vào vị trí thiết bị cho bạn, khi bạn gọi getString()hoặc khi tham chiếu các chuỗi trong XML thông qua @string/mystring. Những cái từ res/values/strings.xmllà những cái dự phòng, nếu bạn không có một thư mục bao gồm ngôn ngữ người dùng, cái này sẽ được sử dụng làm giá trị mặc định.

Xem Bản địa hóacung cấp tài nguyên để biết thêm thông tin.


23
Nếu bạn đang ở trong một android.support.v4.app.Fragment, bạn chỉ có thể gọi getString(R.string.mystring)trực tiếp.
JaKXz

3
Tôi vừa mới chao đảo. Tại sao nó được thực hiện (bởi google) theo cách phức tạp như vậy? Đầu tiên lấy ID số bí ẩn (từ đối tượng R) và sau đó lấy chuỗi bằng ID đó? Và cặp "ID-of-mystring => RealisticValue" thực sự nằm ở đâu? Theo như tôi biết mystring => ID-of-mystring là trong R.java, nhưng đó là nó :)
Lukáš Radek

2
đảm bảo rằng "R" là R dự án của bạn chứ không phải Android mặc định R.
ralphgabb

2
Đây có thể là câu trả lời cần thiết nhưng nó không phải là câu hỏi được yêu cầu! Để tự động truy cập tài nguyên chuỗi theo tên, hãy xem câu trả lời từ @leonvian ... phải là IMO được chấp nhận
Chris Hatton

321

Tôi có cùng một vấn đề. Nhưng mã này dưới đây hoạt động với tôi: Xác minh xem tên gói của bạn có đúng không. Bạn phải tham khảo gói gốc của ứng dụng Android.

private String getStringResourceByName(String aString) {
      String packageName = getPackageName();
      int resId = getResources().getIdentifier(aString, "string", packageName);
      return getString(resId);
    }

9
Trong trường hợp ai đó có lý do chính đáng để làm điều này (ví dụ: tệp dữ liệu chứa chuỗi tùy chỉnh quyết định chuỗi tài nguyên nào sẽ được hiển thị hoặc nếu chuỗi này được tìm nạp từ Internet) - thì tôi muốn chỉ ra rằng Giải pháp này là chính xác. Đặc biệt là chính xác phần mà loại tài nguyên là stringvà không strings. Bởi vì điều đó hợp lý (như phần còn lại của Android). Vì vậy, cảm ơn vì điều đó (và hơn thế nữa), @leonvian. :-)
Ivan Vučica

2
@Sameer để lấy một mảng bằng Chuỗi chỉ cần sử dụng: res.getStringArray (R.array.planets_array); Hãy xem liên kết chính thức này: developer.android.com/guide/topics/resource/
leonvian

3
Mát mẻ. Để thoát khỏi một khai báo phương thức riêng biệt, điều này có thể được "đơn giản hóa" theo cách như vậy : String someStringFromXML = getString(getResources().getIdentifier("some_string_name", "string", getPackageName()));.
Chất dẫn truyền thần kinh

80

Không chỉ từ các hoạt động:

    public static String getStringByIdName(Context context, String idName) {
        Resources res = context.getResources();
        return res.getString(res.getIdentifier(idName, "string", context.getPackageName()));
    }

nó làm việc rất cảm ơn bạn
Mosa

39
getResources().getString(getResources().getIdentifier("propertyName", "string", getPackageName()))

26

Tôi sẽ thêm một cái gì đó vào giải pháp của leonvian, vì vậy nếu có thể tìm thấy chuỗi trong số các tài nguyên (giá trị trả về 0, đó không phải là mã tài nguyên hợp lệ), hàm có thể trả về một cái gì đó:

private String getStringResourceByName(String aString) {
    String packageName = getPackageName();
    int resId = getResources()
            .getIdentifier(aString, "string", packageName);
    if (resId == 0) {
        return aString;
    } else {
        return getString(resId);
    }
}

15

Cách tiếp cận tốt nhất

App.getRes().getString(R.string.some_id)

Sẽ làm việc ở mọi nơi (Utils, Model cũng).

Tôi đã đọc tất cả các câu trả lời, tất cả các câu trả lời có thể làm cho công việc của bạn được thực hiện.

  • Bạn có thể sử dụng getString(R.string.some_string_id)trong cả hai Activityhoặc Fragment.
  • Bạn có thể sử dụng Context.getString(R.string.some_string_id)ở nơi bạn không có quyền truy cập trực tiếp vào getString()phương thức. Thích Dialog.

Vấn đề

Khi bạn không có Contextquyền truy cập , như một phương thức trong Utillớp của bạn .

Giả sử phương pháp dưới đây không có ngữ cảnh.

public void someMethod(){
    ...
    // can't use getResource() or getString() without Context.
}

Bây giờ bạn sẽ vượt qua Contextnhư một tham số trong phương thức này và sử dụnggetString().

public void someMethod(Context context){
    ...
    context.getString(R.string.some_id);
}

Những gì tôi làm là

public void someMethod(){
    ...
    App.getAppResources().getString(R.string.some_id)
}

Gì? Nó rất đơn giản để sử dụng bất cứ nơi nào trong ứng dụng của bạn!

Vì vậy, đây là một giải pháp mà bạn có thể truy cập tài nguyên từ bất cứ nơi nào như thế Util class.

import android.app.Application;
import android.content.res.Resources;

public class App extends Application {
    private static Resources resources;

    @Override
    public void onCreate() {
        super.onCreate();

        resources = getResources();
    }

    public static Resources getAppResources() {
        return resources;
    }

}

Thêm trường tên vào manifest.xml <applicationthẻ của bạn .

<application
        android:name=".App"
        ...
        >
        ...
    </application>

Bây giờ bạn tốt để đi. Sử dụng App.getAppResources().getString(R.string.some_id)bất cứ nơi nào trong ứng dụng.


+1 giải pháp đơn giản & sạch sẽ. Thông báo chính tả xấu getResourses, getResourcessẽ gây ra ghi đè. Ngoài ra mẫu singleton dường như không cần thiết, có thể có thể bỏ qua. Bất kỳ vấn đề rò rỉ bộ nhớ với giải pháp này?
Xarvalus

@Xarvalus Điều này có làm rò rỉ bộ nhớ không?
Khemraj

trong ứng dụng của tôi đều ổn cả :) chỉ tự hỏi liệu có ai có vấn đề gì với nó không. Tôi sẽ cho biết nếu tôi gặp bất kỳ cạm bẫy.
Xarvalus

1
@Xarvalus Rò rỉ bộ nhớ thường xảy ra tại nơi một biến đang được sử dụng ngay cả lớp cha bị phá hủy. Giống như trong Hoạt động, Mảnh vỡ. Tôi không nghĩ rằng nó sẽ xảy ra trong trường hợp này.
Khemraj


14

Một cách đơn giản để nhận chuỗi tài nguyên từ chuỗi vào TextView. Ở đây resourceName là tên của tài nguyên

int resID = getResources().getIdentifier(resourceName, "string", getPackageName());
textview.setText(resID);

7

Nếu bạn không có tài liệu tham khảo Hoạt động, bạn có thể sử dụng ngữ cảnh của mình theo cách này:

getContext().getString(R.string.your_string_name);

4

Ngoài ra còn có một bộ các chuỗi Android được xác định trước như "Ok", "Hủy" và nhiều chuỗi khác - vì vậy bạn không phải khai báo tất cả. Chúng có sẵn đơn giản bằng cách:

getString(android.R.string.ok)

(Trong trường hợp này, chuỗi "Ok"). BTW cũng có các tài nguyên Android khác có sẵn như ví dụ hình ảnh biểu tượng, v.v.


2

Chuỗi myString = getString (R.opes.mystring);

cách dễ dàng


1

Bạn có thể thử điều này trong một Hoạt động:

getResources().getString(R.string.your string name);

Trong các tình huống khác như mảnh vỡ, ... sử dụng

getContext().getResources().getString(R.string.your string name);

0

Để an toàn, bạn nên thêm: mContext.getResource (). GetString (R.opes.your_opes);

mContext có thể là: bối cảnh trong onAttach () của Fragment hoặc this of Activity.


0

Nếu bạn không nhận được nó trong một hoạt động hoặc Fragmnet, thì:

getContext().getResources().getString(R.string.string_name);

Nếu bạn muốn lấy nó từ một lớp bên ngoài hoạt động hoặc đoạn mà bạn không có bối cảnh hoạt động thì hãy sử dụng bối cảnh ứng dụng:

getApplicationContext().getResources().getString(R.string.string_name);

0
R.string.<string_name>

Sử dụng dòng đó trực tiếp trong tập tin java của bạn. Giữ cho nó đơn giản.

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.