Как вызвать getResources() из класса, который не имеет контекста?

В моем приложении у меня много классов и занятий. Droid — это класс, у которого нет контекста. Mygame — это класс, который расширяет SurfaceView и реализует SurfaceHolder.Callback. Я создаю объект Droid в классе mygame и устанавливаю для него фоновое изображение и положение. Код, который я написал для этого, приведен ниже.

block1 = new Droid(BitmapFactory.decodeResource(getResources(), R.drawable.birdpic), 100, 10);

Конструктор класса Droid приведен ниже.

public Droid(Bitmap bitmap, int x, int y) {

    this.bitmap = bitmap;
    this.x = x;
    this.y = y;
}   

В конкретном сценарии мне нужно установить фоновое изображение и положение объекта Droid из самого класса Droid. Здесь я столкнулся с проблемой. Ниже приведен фрагмент кода для этого.

if(checkflag)
{
    myObj.centerblock=new Droid(BitmapFactory.decodeResource(getResources(), R.drawable.blast), myObj.xpos, myObj.ypos);
}   

Проблема в том, что у класса Droid нет контекста. Поэтому я не могу использовать здесь getResources(). Я пробовал код ниже, но он падает.

if(checkflag)
{
    myObj.centerblock=new Droid(BitmapFactory.decodeResource(myObj.getResources(), R.drawable.blast), myObj.xpos, myObj.ypos);
}

Кто-нибудь может мне помочь. Я просто хочу установить фоновое изображение и расположить его для объекта Droid из самого класса Droid.


person andro-girl    schedule 23.11.2011    source источник
comment
возможный дубликат Использование getResources() в классе без активности   -  person Richard Le Mesurier    schedule 21.05.2014


Ответы (5)


Контекст — это дескриптор системы; он предоставляет такие услуги, как разрешение ресурсов, получение доступа к базам данных и предпочтениям и так далее. Это «интерфейс», который позволяет получить доступ к конкретным ресурсам приложения, классу и информации о среде приложения. Ваши действия и службы также расширяют контекст, чтобы они наследуют все эти методы для доступа к информации о среде, в которой работает приложение.

Это означает, что вам необходимо передать контекст конкретному классу, если вы хотите получить/изменить определенную информацию о ресурсах. Вы можете передать контекст в конструкторе, например

public classname(Context context, String s1) 
{
...
}
person Ali    schedule 23.11.2011
comment
можно ли установить контекст для класса Droid... он не расширяет активность или какие-либо другие классы - person andro-girl; 23.11.2011
comment
ему не нужно расширять деятельность. Вы можете передать контекст этому классу при инициализации этого класса из какой-либо активности. - person Ali; 23.11.2011

Обычным решением для этого является передача экземпляра контекста в класс при его создании или после его первого создания, но до того, как вам понадобится использовать контекст.

Другим решением является создание объекта Application со статическим методом для доступа к контексту приложения, хотя это довольно тесно связывает объект Droid с кодом.

Изменить, добавлены примеры

Либо измените класс Droid, чтобы он был примерно таким

 public Droid(Context context,int x, int y) {
    this.bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.birdpic);
    this.x = x;
    this.y = y;
    }   

Или создайте приложение примерно так:

public class App extends android.app.Application
{
    private static App mApp = null;
    /* (non-Javadoc)
     * @see android.app.Application#onCreate()
     */
    @Override
    public void onCreate()
    {
        super.onCreate();
        mApp = this;
    }
    public static Context context()
    {
        return mApp.getApplicationContext();
    }
}

И вызывайте App.context() везде, где вам нужен контекст - обратите внимание, однако, что не все функции доступны в контексте приложения, некоторые доступны только в контексте активности, но это, безусловно, подойдет для вашей потребности в getResources().

Обратите внимание, что вам нужно будет добавить android:name в определение вашего приложения в манифесте, примерно так:

<application
    android:icon="@drawable/icon"
    android:label="@string/app_name"
    android:name=".App" >
person zeetoobiker    schedule 23.11.2011
comment
Использование растрового изображения Android также обеспечивает тесную связь с кодом Android. Я обычно пытаюсь разделить код, связанный с интерфейсом, и специфические вещи приложения (мне не очень удается) - person Konstantin Pribluda; 23.11.2011
comment
@zeetoobiker ... не могли бы вы объяснить эти вещи? Я не понимаю вас .. я не так хорошо знаком с Android. - person andro-girl; 23.11.2011
comment
На самом деле я не имел в виду тесную связь с кодом Android (при условии, что вы предоставили ему доступ к объекту приложения с помощью статического метода), а скорее то, что класс Droid будет тесно связан с проектом, в котором он находится в настоящее время - вы не сможете использовать его в другом проекте, не переписывая внутренности. Честно говоря, класс в приложении для Android, связанный с функциями отображения, будет тесно связан с Android, поэтому я бы не стал об этом беспокоиться. - person zeetoobiker; 24.11.2011
comment
seethalakshim - я добавил несколько примеров к ответу, чтобы, надеюсь, объяснить его немного больше. - person zeetoobiker; 24.11.2011
comment
Findbugs говорит, что запись статической переменной из метода экземпляра, как правило, является плохой практикой, мне любопытно, почему этот подход может быть в порядке, учитывая тот факт, что это что-то специфичное для Android. - person r1k0; 11.06.2014
comment
Итак, должен ли объект App использоваться как синглтон (объект)? - person Bruiser; 27.10.2014
comment
Я думаю, что статический доступ может вызвать проблемы с Garbace Collector. Есть ли способ предотвратить это? - person andreas; 09.09.2015

Пример: Получение строки app_name:

Resources.getSystem().getString( R.string.app_name )
person clive    schedule 25.02.2013
comment
Это использует только системные ресурсы, а не ресурсы приложения, что в 99% случаев не будет работать. - person Adam; 18.03.2013
comment
да... мне тоже не помогло. Мне нужно было добраться до ресурсов приложения для перевода перечисления в строки, и они не были найдены. В итоге пришлось создать функцию, которая сопоставляла перечисление с ресурсом и использовала действие, о чем говорилось в другом месте в этом посте. - person Go Rose-Hulman; 04.03.2014

Это всегда работает для меня:

import android.app.Activity;
import android.content.Context;

public class yourClass {

 Context ctx;

 public yourClass (Handler handler, Context context) {
 super(handler);
    ctx = context;
 }

 //Use context (ctx) in your code like this:
 block1 = new Droid(BitmapFactory.decodeResource(ctx.getResources(), R.drawable.birdpic), 100, 10);
 //OR
 builder.setLargeIcon(BitmapFactory.decodeResource(ctx.getResources(), R.drawable.birdpic));
 //OR
 final Intent intent = new Intent(ctx, MainActivity.class);
 //OR
 NotificationManager notificationManager = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
 //ETC...

}

Не связано с этим вопросом, но пример использования фрагмента для доступа к системным ресурсам/действиям следующим образом:

public boolean onQueryTextChange(String newText) {
 Activity activity = getActivity();
 Context context = activity.getApplicationContext();
 returnSomething(newText);
 return false;
}

View customerInfo = getActivity().getLayoutInflater().inflate(R.layout.main_layout_items, itemsLayout, false);
 itemsLayout.addView(customerInfo);
person Elroy    schedule 21.02.2015

Это можно легко сделать, если вы объявили класс, который расширяется от Application

Этот класс будет похож на синглтон, поэтому, когда вам нужен контекст, вы можете получить его так:

Я думаю, что это лучший ответ и чище

Вот мой код из пакета Utilities:

 public static String getAppNAme(){
     return MyOwnApplication.getInstance().getString(R.string.app_name);
 }
person Catluc    schedule 05.10.2016