getString Di Luar Konteks atau Aktivitas


260

Saya telah menemukan R.stringcukup bagus untuk menjaga string hardcoded dari kode saya, dan saya ingin tetap menggunakannya dalam kelas utilitas yang berfungsi dengan model-model dalam aplikasi saya untuk menghasilkan output. Misalnya, dalam hal ini saya membuat email dari model di luar kegiatan.

Apakah mungkin menggunakan di getStringluar ContextatauActivity ? Saya kira saya bisa lulus dalam aktivitas saat ini, tetapi tampaknya tidak perlu. Harap perbaiki saya jika saya salah!

Sunting: Bisakah kita mengakses sumber daya tanpa menggunakan Context?


4
Dengan meneruskan konteks ke kelas yang akan menggunakan string, Anda juga menyampaikan informasi tentang bahasa apa (en, es, dll) yang digunakan oleh aplikasi. Jadi, jika Anda memiliki dua strings.xml, ia akan tahu mana yang akan digunakan
olahraga

Jawaban:


440

Ya, kami dapat mengakses sumber daya tanpa menggunakan `Konteks`

Kamu bisa memakai:

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

... di mana-mana di aplikasi Anda, bahkan dalam deklarasi konstanta statis. Sayangnya, ini hanya mendukung sumber daya sistem .

Untuk sumber daya lokal gunakan solusi ini . Itu tidak sepele, tetapi berhasil.


17
apa yang dimaksud dengan sumber daya sistem? strings.xml adalah sumber daya sistem atau tidak? Bagi saya itu tidak berhasil, mengatakan tidak dapat menemukan sumber daya.
kirhgoff

6
Sumber daya sistem milik Android pada perangkat. strings.xml hanya milik aplikasi Anda. Cari solusi stackoverflow.com/a/4391811/715269
Gangnus

3
Ini adalah solusi elegan untuk kelas-kelas Pabrik saat mengakses string. Saya tidak menikmati melewati Konteks di mana-mana. Itu hanya kekacauan yang tidak perlu untuk contoh di mana kita benar-benar hanya ingin string disimpan secara global.
Jay Snayder

1
Apakah ini lebih efisien daripada meneruskan konteks ke kelas dan menggunakannya ??
SoliQuiD

5
saya mendapatkan kesalahan iniandroid.content.res.Resources$NotFoundException: String resource ID #0x7f0f0061
Ebrahim Karimi

108

Sayangnya, satu-satunya cara Anda dapat mengakses sumber daya string apa pun adalah dengan Context(yaitu, Activityatau Service). Apa yang biasanya saya lakukan dalam kasus ini, adalah hanya meminta penelepon untuk lulus dalam konteks.


4
Terima kasih atas tipnya! Saya baru saja mencoba ini, tetapi untuk beberapa alasan saya mendapat kesalahan kompilasi ketika saya mencoba:ctx.getString(ctx.R.string.blah);
SapphireSun

Saya akan mengajukan argumen ke metode util tipe Contextsehingga Anda dapat menggunakannya dari Aktivitas atau Layanan.
MatrixFrog

2
Anda tidak perlu ctx.R.string.blah, cukup gunakanR.string.blah
Pentium10

2
Saya tidak yakin dari mana symbol not found errordatangnya, tetapi pastikan Anda telah Rmengimpor di atas kelas.
Pentium10

11
Jawabannya adalah SALAH. Kunjungi yang berikutnya. :-)
Gangnus

33

Di MyApplication, yang meluas Application:

public static Resources resources;

Dalam MyApplication's onCreate:

resources = getResources();

Sekarang Anda dapat menggunakan bidang ini dari mana saja di aplikasi Anda.


Apakah akan bekerja melalui layanan? (Terutama ketika Android membunuh aplikasi dan hanya memulai layanan)
Atul

1
Ya, Android mulai menjalankan kode Anda dengan memanggil Application.onCreate dan setelah itu menjalankan layanan Anda.
konmik

23

BTW, salah satu alasan simbol tidak ditemukan kesalahan mungkin karena IDE Anda mengimpor android.R; kelas bukan milikmu satu. Cukup ganti impor android.R; untuk mengimpor your.namespace.R;

Jadi 2 hal dasar untuk membuat string terlihat di kelas yang berbeda:

//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

Pendekatan Unik

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

Ini akan bekerja di mana saja di aplikasi. ( Kelas Util, Dialog, Fragmen atau kelas apa pun di aplikasi Anda )

(1) Buat atau Edit (jika sudah ada) Applicationkelas Anda .

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) Tambahkan bidang nama ke manifest.xml <applicationtag Anda .

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

Sekarang kamu baik untuk pergi. Gunakan App.getRes().getString(R.string.some_id)di mana saja di aplikasi.


1
Saya pribadi menyukai pendekatan ini. Nyaman untuk mendapatkan sumber daya string khusus dari mana saja dalam kode.
skakmat711

Apakah ada masalah keamanan dengan solusi ini?
nibbana

@ user1823280 Tidak, saya tidak berpikir.
Khemraj

Solusi sempurna
Yasiru Nayanajith

4

Jika Anda memiliki kelas yang Anda gunakan dalam suatu kegiatan dan Anda ingin memiliki akses sumber daya di kelas itu, saya sarankan Anda untuk mendefinisikan konteks sebagai variabel pribadi di kelas dan memulainya dalam konstruktor:

public class MyClass (){
    private Context context;

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

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

Membuat instan kelas dalam aktivitas Anda:

MyClass m=new MyClass(this);

0

Ini akan membuat Anda mendapatkan akses applicationContextdari mana saja memungkinkan Anda untuk mendapatkan di applicationContextmana saja yang dapat menggunakannya; Toast, getString(), sharedPreferences, Dll

Singleton:

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;
    }

}

Inisialisasi Singleton di Applicationsubkelas Anda :

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);
    }
}

Jika saya tidak salah, ini memberi Anda pengait ke applicationContext di mana saja, sebut saja dengan itu. ApplicationContextSingleton.getInstance.getApplicationContext(); Anda tidak perlu menghapus ini di titik mana pun, seperti saat aplikasi ditutup, ini tetap berlaku.

Ingatlah untuk memperbarui AndroidManifest.xmluntuk menggunakan Applicationsubkelas ini :

<?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"
    >

Tolong beri tahu saya jika Anda melihat sesuatu yang salah di sini, terima kasih. :)


0

Pendekatan terbaik dari respons Khemraj:

Kelas aplikasi

class App : Application() {

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


    // MARK: - Lifecycle

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

}

Deklarasi dalam manifes

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

Kelas konstanta

class Localizations {

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

}

Menggunakan

textView.text = Localizations.info

0

Lebih baik menggunakan sesuatu seperti ini tanpa konteks dan aktivitas :

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

0

Entah bagaimana tidak suka solusi hacking dari menyimpan nilai statis jadi datang dengan sedikit lebih lama tetapi versi bersih yang dapat diuji juga.

Ditemukan 2 cara yang mungkin untuk melakukannya-

  1. Lewati context.resources sebagai parameter ke kelas Anda di mana Anda ingin sumber string. Cukup sederhana. Jika melewati sebagai param tidak dimungkinkan, gunakan setter.

misalnya

data class MyModel(val resources: Resources) {
    fun getNameString(): String {
        resources.getString(R.string.someString)
    }
}
  1. Gunakan data-binding (membutuhkan fragmen / aktivitas)

Sebelum Anda membaca: Versi ini digunakan 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>

Kegiatan / Fragmen-

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

Terkadang, Anda perlu mengubah teks berdasarkan bidang dalam model. Jadi Anda akan mengikat data model itu juga dan karena aktivitas / fragmen Anda tahu tentang model tersebut, Anda dapat mengambil nilai dengan sangat baik dan kemudian mengikat data string berdasarkan itu.


0

Anda dapat melakukan ini di Kotlin dengan membuat kelas yang memperluas Aplikasi dan kemudian menggunakan konteksnya untuk memanggil sumber daya di mana saja dalam kode Anda

Kelas Aplikasi Anda akan terlihat seperti ini

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

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

Deklarasikan kelas Aplikasi Anda di AndroidManifest.xml (sangat penting)

<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>

Untuk mengakses mis. File string, gunakan kode berikut

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

Ini tidak akan berfungsi jika Anda mengubah lokal secara terprogram selama runtime karena konteks aplikasi adalah singleton dan diinisialisasi ketika proses Anda dimulai.
Szörényi Ádám

-2

Inilah yang saya lakukan, Di MainActivity Anda, buat variabel statis untuk konteks seperti yang ditunjukkan di bawah ini:

public static Context mContext;

dan di onCreate () inisialisasi mContext untuk ini;

mContext = this;

Kemudian, dalam file tempat Anda ingin mengakses konteks, katakan,

private Context context = MainActivity.mContext;

Sekarang, Anda bisa mendapatkan sumber daya string dengan cara berikut,

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

-8

Saya menggunakan getContext().getApplicationContext().getString(R.string.nameOfString); ini bekerja untuk saya.


14
Apakah Anda pikir getContext()tersedia di mana-mana ?!
Hamzeh Soboh

1
Ini tidak memberikan jawaban atas pertanyaan karena getContext () hanya tersedia di kelas
Umar Ata
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.