Kaynak içeriği statik bir bağlamdan nasıl alabilirim?


168

Ben widget xmlgibi başka bir şey yapmadan önce bir dosyadan dizeleri okumak istiyorum setText, bu yüzden aramak getResources()için bir etkinlik nesnesi olmadan nasıl yapabilirim ?

Yanıtlar:


373
  1. ApplicationÖrneğin, bir alt sınıf oluşturunpublic class App extends Application {
  2. İçindeki etiketinizin android:nameniteliğini yeni sınıfınızı gösterecek şekilde ayarlayın , ör.<application>AndroidManifest.xmlandroid:name=".App"
  3. In onCreate()your bağlamda (örn tasarrufu uygulama örneğinin yöntemi thisadında bir statik alana) mContextve statik yöntemini oluşturmak olduğunu döndürür bu alan, örneğin getContext():

İşte böyle görünmeli:

public class App extends Application{

    private static Context mContext;

    @Override
    public void onCreate() {
        super.onCreate();
        mContext = this;
    }

    public static Context getContext(){
        return mContext;
    }
}

Şimdi şunu kullanabilirsiniz: App.getContext()bir bağlam elde etmek istediğinizde ve sonra getResources()(veya App.getContext().getResources()).


9
Uygulamanın örneği dinamik bir değer değil, nasıl yani @Gangnus? Her halükarda - Android'de statiğe güvenmenin baş ağrısından başka bir şey olmadığını gördüm. "Şimdi görüyorsun, şimdi görmüyorsun"
Bostone

18
Bunun bir 'hack' olduğunu düşünmekten kaçınamıyorum. Her ne kadar ben kullanıyorum (bu çözüm verdiğiniz için btw teşekkürler, çünkü yerelleştirme dışsallaştırmak üzereydi) ben bu kötü duygu olsun, bu bir şekilde yanlış gibi.
Illiax

8
Uygulamanızdaki her bir statik yöntemde ilk parametre olarak Context'ten geçmekten daha mı iyi ya da daha kötü? Birincisi kibirli hissettirir, ancak ikincisi gereksiz yere tekrarlayıcıdır.
Dave

12
Dokümanlar "Uygulamayı alt sınıfa ayırmaya gerek yoktur. Çoğu durumda, statik tek düğmeler aynı işlevselliği daha modüler bir şekilde sağlayabilir. Tek başınızın genel bir bağlama ihtiyacı varsa (örneğin yayın alıcılarını kaydetmek için), alma işlevi buna, singleton'u ilk oluştururken dahili olarak Context.getApplicationContext () yöntemini kullanan bir Context verilebilir. " ~ developer.android.com/reference/android/app/Application.html
David d C e Freitas

25
Bellek sızmasını önlemek için, İçeriği bir WeakReference içinde depolamak daha iyi olur: private static WeakReference <Context> mContext; public static Context getContext () {return mContext.get (); } Bu, uygulama kilitlendiğinde yardımcı olur ve statik içeriği null olarak ayarlayamazsınız (WeakReference çöp toplanabilir).
FrankKrumnow

102

Yalnızca sistem kaynakları için!

kullanım

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

Bunları uygulamanızın her yerinde, statik sabit bildirimlerinde bile kullanabilirsiniz!


2
Çok havalı. Genellikle rahatsız olmaz ... Birisi büyük harf kullandığında: P Şaka yapıyorum. Standart, dizeler ve çekilebilir malzemeler gibi bazı kaynaklar için çalışır ... ancak, belgelerin dediği gibi, yönlendirme önlemleri, vb. Şeyler için iyi çalışmaz. Ayrıca ve en önemlisi, bu bir bunu gerekebilir şeyler için bazen yararlıdır küresel bağlam (bir yükselterek Toast, örneğin bir alma SharedPreferencebenim Latince dil öğretmeni söylediği gibi, bir veritabanı açın örneği: vesaire ).
Cristian

1
Onunla tüm dünyada barışı bile kazanamazsın :-). Ancak burada soru tarafından belirlenen sorunun çözülmesine yardımcı olur. Her görevi çözdüğünü söylemiyorum, sadece görevini neredeyse uygulamanın her yerinde çözdüğünü söylemiyorum. Android'i her zaman kullandığımda 10 ay boyunca böyle bir çözüm aradım. Ve şimdi buldum.
Gangnus

18
Burada dikkatli olmalısın. Bu yöntemi kullanarak uygulama kaynaklarınızı bulmaya çalışmayın. Hassas baskıyı okuyun: Yalnızca sistem kaynaklarına erişim sağlayan (uygulama kaynağı yok) ve geçerli ekran için yapılandırılmamış (boyut birimlerini kullanamaz, yönlendirmeye vb. Göre değişmez) bir genel paylaşılan Kaynaklar nesnesini döndürün.
Bostone

4
@ DroidIn.net Alıntı: "Ama sadece sistem kaynakları için!". Biliyorum / * sigh / *
Gangnus

1
Bunu kullanarak bir istisna aldım: android.content.res.Resources $ NotFoundException: Dize kaynak kimliği
vinidog 29:16

6

Kotlin çözümüm statik bir Uygulama bağlamı kullanmaktır:

class App : Application() {
    companion object {
        lateinit var instance: App private set
    }

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

Ve her yerde kullandığım Strings sınıfı:

object Strings {
    fun get(@StringRes stringRes: Int, vararg formatArgs: Any = emptyArray()): String {
        return App.instance.getString(stringRes, *formatArgs)
    }
}

Böylece kaynak dizgileri elde etmenin temiz bir yoluna sahip olabilirsiniz

Strings.get(R.string.some_string)
Strings.get(R.string.some_string_with_arguments, "Some argument")

Lütfen bu cevabı silmeyin, bir tane bırakayım.


Basit ve temiz bir çözüm, kodu paylaştığınız için teşekkür ederiz!
Jeehut

Teşekkürler! Bu bilinen bir çözüm olmasına rağmen Strings, yardımcı oldu.
CoolMind

4

Başka bir olasılık daha var. OpenGl gölgelendiricileri böyle kaynaklardan yüklüyorum:

static private String vertexShaderCode;
static private String fragmentShaderCode;

static {
    vertexShaderCode = readResourceAsString("/res/raw/vertex_shader.glsl");
    fragmentShaderCode = readResourceAsString("/res/raw/fragment_shader.glsl");
}

private static String readResourceAsString(String path) {
    Exception innerException;
    Class<? extends FloorPlanRenderer> aClass = FloorPlanRenderer.class;
    InputStream inputStream = aClass.getResourceAsStream(path);

    byte[] bytes;
    try {
        bytes = new byte[inputStream.available()];
        inputStream.read(bytes);
        return new String(bytes);
    } catch (IOException e) {
        e.printStackTrace();
        innerException = e;
    }
    throw new RuntimeException("Cannot load shader code from resources.", innerException);
}

Gördüğünüz gibi , sınıfınızın /res/... Değiştir yolundaki herhangi bir kaynağa erişebilirsiniz aClass. Bu aynı zamanda testlerde kaynakları nasıl yüklerim (androidTests)


1
Etkinlik olmadığında benim için çalışan tek çözüm (Uygulamayı genişletebilecek bir sınıf olmadan bir eklenti geliştirmek). Teşekkür ederim +1
itaton

3

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

}

ApplicationAlt sınıfınızdaki Singleton'u başlatı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);
    }
}

Eğer yanılmıyorsam, bu, her yerde applicationContext'e bir kanca verir, onu arayın ApplicationContextSingleton.getInstance.getApplicationContext(); , Uygulama kapandığında olduğu gibi, herhangi bir noktada bunu temizlemeniz gerekmemelidir.

AndroidManifest.xmlBu Applicationalt sınıfı kullanmak için güncellemeyi unutmayın :

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

Artık ApplicationContextSingleton.getInstance (). GetApplicationContext (). GetResources () öğesini her yerden, ayrıca uygulama alt sınıflarının yapamayacağı çok az yerde kullanabilmeniz gerekir.

Burada yanlış bir şey görürseniz lütfen bize bildirin, teşekkür ederim. :)


2

Başka bir çözüm:

Statik olmayan bir dış sınıfta statik bir alt sınıfınız varsa, alt sınıfın içindeki kaynaklara, dış sınıfın oluşturulmasında başlattığınız dış sınıftaki statik değişkenler aracılığıyla erişebilirsiniz. Sevmek

public class Outerclass {

    static String resource1

    public onCreate() {
        resource1 = getString(R.string.text);
    }

    public static class Innerclass {

        public StringGetter (int num) {
            return resource1; 
        }
    }
}

Ben I8N nedeniyle yararlı FragmentActivity içinde statik FragmentPagerAdapter getPageTitle (int konumu) İşlevi için kullandım.


2

Kısayol

Kullandığım App.getRes()yerine App.getContext().getResources()(@Cristian cevap olarak)

Kodunuzun herhangi bir yerinde kullanmak çok basit!

İşte size kaynaklara istediğiniz yerden erişebileceğiniz benzersiz bir çözümUtil class .

(1) ApplicationSınıfınızı oluşturun veya düzenleyin .

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) manifest.xml <applicationEtiketinize ad alanı ekleyin . (veya zaten varsa bunu atla)

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

Şimdi gitmekte fayda var.

Kodda App.getRes().getString(R.string.some_id)herhangi bir yerde kullanın .


0

Bence daha fazla yol mümkün. Ama bazen, bu çözümü kullanıyorum. (tam global):

    import android.content.Context;

    import <your package>.R;

    public class XmlVar {

        private XmlVar() {
        }

        private static String _write_success;

        public static String write_success() {
            return _write_success;
        }


        public static void Init(Context c) {
            _write_success = c.getResources().getString(R.string.write_success);
        }
    }
//After activity created:
cont = this.getApplicationContext();
XmlVar.Init(cont);
//And use everywhere
XmlVar.write_success();

0

Statik fonksiyondan openGL ES için gölgelendirici yüklüyorum.

Dosya ve dizin adınız için küçük harf kullanmanız gerektiğini unutmayın, aksi takdirde işlem başarısız olur

public class MyGLRenderer implements GLSurfaceView.Renderer {

    ...

    public static int loadShader() {
        //    Read file as input stream
        InputStream inputStream = MyGLRenderer.class.getResourceAsStream("/res/raw/vertex_shader.txt");

        //    Convert input stream to string
        Scanner s = new Scanner(inputStream).useDelimiter("\\A");
        String shaderCode = s.hasNext() ? s.next() : "";
    }

    ...

}

0
public Static Resources mResources;

 @Override
     public void onCreate()
     {
           mResources = getResources();
     }

Sorun şu ki, getResources () öğesinin bir içeriğe ihtiyacı var. Yani bu muhtemelen "bir aktivite nesnesi olmadan" için bir çözüm değildir (onCreate () yöntemini yayınladığınız)
Tobias Reich

0

API düzey 27 kullanıyorum ve yaklaşık iki gün boyunca mücadele ettikten sonra en iyi çözümü buldum. Etkinlik veya Uygulamadan türetilmemiş bir sınıftan bir xml dosyasını okumak istiyorsanız, aşağıdakileri yapın.

  1. Testdata.xml dosyasını varlıklar dizinine yerleştirin.

  2. Test veri belgesinin ayrıştırılması için aşağıdaki kodu yazın.

        InputStream inputStream = this.getClass().getResourceAsStream("/assets/testdata.xml");
    
        // create a new DocumentBuilderFactory
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        // use the factory to create a documentbuilder
        DocumentBuilder builder = factory.newDocumentBuilder();
        // create a new document from input stream
        Document doc = builder.parse(inputStream);

-1

Statik işlevi uyguladığınız sınıfınızda, bu sınıftan private \ public yöntemini çağırabilirsiniz . Private \ public yöntemi getResources dosyasına erişebilir .

Örneğin:

public class Text {

   public static void setColor(EditText et) {
      et.resetColor(); // it works

      // ERROR
      et.setTextColor(getResources().getColor(R.color.Black)); // ERROR
   }

   // set the color to be black when reset
   private void resetColor() {
       setTextColor(getResources().getColor(R.color.Black));
   }
}

ve diğer \ etkinlik \ sınıfından şunları arayabilirsiniz:

Text.setColor('some EditText you initialized');

-1

bir bağlamınız varsa, yani içeride;

public void onReceive(Context context, Intent intent){

}

kaynakları almak için bu kodu kullanabilirsiniz:

context.getResources().getString(R.string.app_name);

2
Sorunun başlığı statik bir bağlamda söylüyor. Hangi cevabınızı kapsamıyor.
Rune Schjellerup Philosof
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.