getString Bên ngoài bối cảnh hoặc hoạt động


260

Tôi đã thấy R.stringkhá tuyệt vời khi giữ các chuỗi mã hóa cứng khỏi mã của mình và tôi muốn tiếp tục sử dụng nó trong một lớp tiện ích hoạt động với các mô hình trong ứng dụng của tôi để tạo đầu ra. Chẳng hạn, trong trường hợp này tôi đang tạo một email từ một mô hình bên ngoài hoạt động.

Có thể sử dụng getStringbên ngoài một ContexthoặcActivity ? Tôi cho rằng tôi có thể vượt qua trong hoạt động hiện tại, nhưng có vẻ như không cần thiết. Vui long sửa cho tôi nêu tôi sai!

Chỉnh sửa: Chúng tôi có thể truy cập các tài nguyên mà không cần sử dụng Context?


4
Bằng cách chuyển ngữ cảnh đến lớp sẽ sử dụng chuỗi, bạn cũng sẽ truyền thông tin về ngôn ngữ nào (en, es, v.v.) đang được ứng dụng sử dụng. Vì vậy, nếu bạn có hai chuỗi XML, nó sẽ biết nên sử dụng chuỗi nào
thể thao

Câu trả lời:


439

Có, chúng ta có thể truy cập tài nguyên mà không cần sử dụng `Context`

Bạn có thể dùng:

Resources.getSystem().getString(android.R.string.somecommonstuff)

... ở mọi nơi trong ứng dụng của bạn, ngay cả trong các khai báo hằng tĩnh. Thật không may, nó chỉ hỗ trợ tài nguyên hệ thống .

Đối với tài nguyên địa phương sử dụng giải pháp này . Nó không tầm thường, nhưng nó hoạt động.


17
tài nguyên hệ thống có nghĩa là gì? chuỗi DOM có phải là tài nguyên hệ thống hay không? Đối với tôi nó không hoạt động, nói không thể tìm thấy tài nguyên.
kirhgoff

6
Tài nguyên hệ thống thuộc về Android trên thiết bị. String.xml chỉ thuộc về ứng dụng của bạn. Tìm kiếm giải pháp stackoverflow.com/a/4391811/715269
Gangnus 15/03/13

3
Đây là một giải pháp tao nhã cho các lớp Factory khi truy cập chuỗi. Tôi không thích đi dọc theo Bối cảnh ở khắp mọi nơi. Đó chỉ là sự lộn xộn không cần thiết cho các trường hợp mà chúng ta thực sự chỉ muốn một chuỗi được lưu trữ trên toàn cầu.
Jay Snayder

1
điều này có hiệu quả hơn việc chuyển ngữ cảnh đến một lớp và sử dụng nó không ??
SoliQuiD

5
tôi nhận được lỗi nàyandroid.content.res.Resources$NotFoundException: String resource ID #0x7f0f0061
Ebrahim Karimi

108

Thật không may, cách duy nhất bạn có thể truy cập vào bất kỳ tài nguyên chuỗi nào là với một Context(tức là một Activityhoặc Service). Những gì tôi thường làm trong trường hợp này, chỉ đơn giản là yêu cầu người gọi vượt qua trong ngữ cảnh.


4
Cảm ơn vì tiền hỗ trợ! Tôi mới thử cái này, nhưng vì một số lý do tôi đã gặp lỗi biên dịch khi tôi thử:ctx.getString(ctx.R.string.blah);
SapphireSun

Tôi sẽ đưa ra đối số cho các phương thức Contextsử dụng loại để bạn có thể sử dụng nó từ Hoạt động hoặc Dịch vụ.
MatrixFrog

2
Bạn không cần ctx.R.string.blah, chỉ cần sử dụngR.string.blah
Pentium10

2
Tôi không chắc chắn từ đâu symbol not found errorđến, nhưng hãy chắc chắn rằng bạn đã Rnhập vào đầu lớp.
Pentium10

11
Câu trả lời là SAI. Vis cái tiếp theo. :-)
Gangnus

33

Trong MyApplicationđó, mở rộng Application:

public static Resources resources;

Trong MyApplication's onCreate:

resources = getResources();

Bây giờ bạn có thể sử dụng lĩnh vực này từ bất cứ nơi nào trong ứng dụng của bạn.


Nó sẽ hoạt động thông qua dịch vụ? (Đặc biệt khi Android tắt ứng dụng và chỉ bắt đầu dịch vụ)
Atul

1
Có, Android bắt đầu thực thi mã của bạn bằng cách gọi Application.onCreate và sau đó, nó chạy dịch vụ của bạn.
konmik

23

BTW, một trong những lý do lỗi không tìm thấy biểu tượng có thể là do IDE của bạn đã nhập android.R; lớp thay vì của bạn Chỉ cần thay đổi nhập android.R; để nhập your.namespace.R;

Vì vậy, 2 điều cơ bản để có được chuỗi hiển thị trong lớp khác nhau:

//make sure you are importing the right R class
import your.namespace.R;

//don't forget about the context
public void some_method(Context context) {
   context.getString(R.string.YOUR_STRING);
}

19

Phương pháp độc đáo

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

Điều này sẽ làm việc ở mọi nơi trong ứng dụng. ( Lớp Util, Hộp thoại, Đoạn hoặc bất kỳ lớp nào trong ứng dụng của bạn )

(1) Tạo hoặc chỉnh sửa (nếu đã tồn tại) Applicationlớp của bạn .

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

public class App extends Application {
    private static App mInstance;
    private static Resources res;


    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
        res = getResources();
    }

    public static App getInstance() {
        return mInstance;
    }

    public static Resources getResourses() {
        return res;
    }

}

(2) 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.getRes().getString(R.string.some_id)bất cứ nơi nào trong ứng dụng.


1
Cá nhân tôi thích cách tiếp cận này. Thuận tiện để có được tài nguyên chuỗi tùy chỉnh từ bất cứ nơi nào trong mã.
checkmate711

Có bất kỳ vấn đề bảo mật với giải pháp này?
niết bàn

@ user1823280 Không, tôi không nghĩ vậy.
Khemraj

Giải pháp hoàn hảo
Yasiru Nayanajith

4

Nếu bạn có một lớp mà bạn sử dụng trong một hoạt động và bạn muốn có quyền truy cập vào nguồn tài nguyên trong lớp đó, tôi khuyên bạn nên xác định một bối cảnh là một biến riêng tư trong lớp và khởi tạo nó trong hàm tạo:

public class MyClass (){
    private Context context;

    public MyClass(Context context){
       this.context=context;
    }

    public testResource(){
       String s=context.getString(R.string.testString).toString();
    }
}

Tạo một lớp học ngay lập tức trong hoạt động của bạn:

MyClass m=new MyClass(this);

0

Điều này sẽ giúp bạn truy cập applicationContexttừ bất cứ đâu cho phép bạn đến applicationContextbất cứ nơi nào có thể sử dụng nó; Toast, getString(), sharedPreferencesVv

Người độc thân:

package com.domain.packagename;

import android.content.Context;

/**
 * Created by Versa on 10.09.15.
 */
public class ApplicationContextSingleton {
    private static PrefsContextSingleton mInstance;
    private Context context;

    public static ApplicationContextSingleton getInstance() {
        if (mInstance == null) mInstance = getSync();
        return mInstance;
    }

    private static synchronized ApplicationContextSingleton getSync() {
        if (mInstance == null) mInstance = new PrefsContextSingleton();
        return mInstance;
    }

    public void initialize(Context context) {
        this.context = context;
    }

    public Context getApplicationContext() {
        return context;
    }

}

Khởi tạo Singleton trong Applicationlớp con của bạn :

package com.domain.packagename;

import android.app.Application;

/**
 * Created by Versa on 25.08.15.
 */
public class mApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        ApplicationContextSingleton.getInstance().initialize(this);
    }
}

Nếu tôi không sai, điều này mang lại cho bạn một liên kết với applicationContext ở mọi nơi, hãy gọi nó với ApplicationContextSingleton.getInstance.getApplicationContext(); Bạn không nên xóa điều này bất cứ lúc nào, vì khi ứng dụng đóng, dù sao thì nó cũng đi theo.

Hãy nhớ cập nhật AndroidManifest.xmlđể sử dụng Applicationlớp con này :

<?xml version="1.0" encoding="utf-8"?>

<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.domain.packagename"
    >

<application
    android:allowBackup="true"
    android:name=".mApplication" <!-- This is the important line -->
    android:label="@string/app_name"
    android:theme="@style/AppTheme"
    android:icon="@drawable/app_icon"
    >

Xin vui lòng cho tôi biết nếu bạn thấy bất cứ điều gì sai ở đây, cảm ơn bạn. :)


0

Cách tiếp cận tốt nhất từ ​​phản ứng của Khemraj:

Lớp ứng dụng

class App : Application() {

    companion object {
        lateinit var instance: Application
        lateinit var resourses: Resources
    }


    // MARK: - Lifecycle

    override fun onCreate() {
        super.onCreate()
        instance = this
        resourses = resources
    }

}

Tuyên bố trong bảng kê khai

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

Lớp hằng

class Localizations {

    companion object {
        val info = App.resourses.getString(R.string.info)
    }

}

Sử dụng

textView.text = Localizations.info

0

Tốt hơn là sử dụng một cái gì đó như thế này mà không có bối cảnhhoạt động :

Resources.getSystem().getString(R.string.my_text)

0

Bằng cách nào đó, chúng tôi không thích các giải pháp lưu trữ giá trị tĩnh để tìm ra một chút lâu hơn nhưng phiên bản sạch cũng có thể được kiểm tra.

Tìm thấy 2 cách có thể để làm điều đó-

  1. Truyền ngữ cảnh.resres dưới dạng tham số cho lớp của bạn nơi bạn muốn tài nguyên chuỗi. Khá đơn giản. Nếu vượt qua như param là không thể, sử dụng setter.

ví dụ

data class MyModel(val resources: Resources) {
    fun getNameString(): String {
        resources.getString(R.string.someString)
    }
}
  1. Sử dụng liên kết dữ liệu (yêu cầu phân đoạn / hoạt động)

Trước khi bạn đọc: Phiên bản này sử dụng Data binding

XML-

<?xml version="1.0" encoding="utf-8"?>

<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<data>
    <variable
        name="someStringFetchedFromRes"
        type="String" />
</data>

<TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@{someStringFetchedFromRes}" />
</layout>

Hoạt động / Mảnh vỡ-

val binding = NameOfYourBinding.inflate(inflater)
binding.someStringFetchedFromRes = resources.getString(R.string.someStringFetchedFromRes)

Đôi khi, bạn cần thay đổi văn bản dựa trên một trường trong mô hình. Vì vậy, bạn cũng sẽ liên kết dữ liệu với mô hình đó và vì hoạt động / đoạn của bạn biết về mô hình, bạn có thể tìm nạp giá trị rất tốt và sau đó liên kết dữ liệu dựa trên chuỗi đó.


0

Bạn có thể làm điều này trong Kotlin bằng cách tạo một lớp mở rộng Ứng dụng và sau đó sử dụng ngữ cảnh của nó để gọi các tài nguyên ở bất cứ đâu trong mã của bạn

Lớp ứng dụng của bạn sẽ trông như thế này

 class App : Application() {
    override fun onCreate() {
        super.onCreate()
        context = this
    }

    companion object {
        var context: Context? = null
            private set
    }
}

Khai báo lớp Ứng dụng của bạn trong AndroidManifest.xml (rất quan trọng)

<application
        android:allowBackup="true"
        android:name=".App" //<--Your declaration Here
        ...>
        <activity
            android:name=".SplashActivity"  android:theme="@style/SplashTheme">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity android:name=".MainActivity"/>
    </application>

Để truy cập ví dụ: tệp chuỗi sử dụng mã sau

App.context?.resources?.getText(R.string.mystring)

Điều này sẽ không hoạt động nếu bạn thay đổi ngôn ngữ lập trình trong thời gian chạy vì bối cảnh ứng dụng là một đơn vị và được khởi tạo khi quá trình của bạn bắt đầu.
Szorényi Ádám

-2

Đây là những gì tôi đã làm, trong MainActivity của bạn, tạo một biến tĩnh cho bối cảnh như dưới đây:

public static Context mContext;

và trong phần khởi tạo onCreate () mContext cho điều này;

mContext = this;

Sau đó, trong tệp mà bạn muốn truy cập vào ngữ cảnh, giả sử

private Context context = MainActivity.mContext;

Bây giờ, bạn có thể nhận được một tài nguyên chuỗi theo cách sau,

String myString = context.getResources().getString(R.string.resource_id);

-8

Tôi đã sử dụng getContext().getApplicationContext().getString(R.string.nameOfString); Nó làm việc cho tôi.


14
Bạn có nghĩ getContext()là có sẵn ở khắp mọi nơi?!
Hamzeh Soboh

1
Điều này không cung cấp câu trả lời cho câu hỏi vì getContext () chỉ khả dụng trong các lớp kích hoạt và phân đoạn
Umar Ata
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.