在非活动类中使用getResources()


123

我正在尝试在非活动类中使用getResources方法。如何获得对“资源”对象的引用,以便可以访问资源文件夹下存储的xml文件?

例:

XmlPullParser xpp = getResources().getXml(R.xml.samplexml);

Context在Android中传递对象通常不是一个好主意。它可能导致内存泄漏。请参阅我的答案,以寻求风险较小的解决方案。
杰森·克罗斯比

Answers:


147

您将必须将一个context对象传递给它。要么this,如果你有在activty到类的引用,或getApplicationContext()

public class MyActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        RegularClass regularClass = new RegularClass(this);
    }
}

然后,可以在构造函数中使用它(或将其设置为实例变量):

public class RegularClass(){
    private Context context;

    public RegularClass(Context current){
        this.context = current;
    }

    public findResource(){
        context.getResources().getXml(R.xml.samplexml);
    }
}

构造函数接受Context为参数的地方


7
Context在Android中传递对象通常不是一个好主意。它可能导致内存泄漏。
杰森·克罗斯比

28
作为基本的经验法则,但是我觉得这有点误导。Context对象是令人讨厌的,因为它在应用程序范围或活动范围内并不是立即显而易见的。提供错误的内存泄漏(和崩溃)。例如,向Activity需要a的静态对象提供an ,Context并且当Activityis导致Activity在onDestroy之后持续存在时,该对象不会被销毁,因为由于另一个静态对象而无法对其进行GC处理。所以是的,这可能很危险,但是在这里要提到我知道为什么感到危险的重要性。
Dororo 2014年

2
^ Dororo,这是我读过的最重要的评论之一。很少讨论是否适当使用上下文。因此,我感到自己遇到了许多无法解释的错误!
乔纳森·邓恩

@Dororo那么您有什么练习建议吗?我们是否应该避免传递上下文变量?那么,当我们需要来自活动类的一些api时,我们该怎么办?
Alston

35

传递Context对象不是一个好主意。这通常会导致内存泄漏。我的建议是您不要这样做。我制作了许多Android应用程序,而不必将上下文传递给应用程序中的非活动类。一个更好的想法是让你需要访问,而你在资源ActivityFragment,并紧紧抓住它的另一个类。然后,您可以在应用程序的任何其他类中使用该类来访问资源,而不必传递Context对象。


这是很好的建议,谢谢。在SQLiteOpenHelper中会出现问题吗?在构造函数中,您必须传递上下文。在其他方法中不再可用,但是我可以将其存储在私有字段中。
彼得

2
@Peter是的,有些类要求您传递上下文对象。因此,最好尝试仅在活动或片段中使用诸如SqLiteOpenHelper之类的类,这样就不必传递上下文对象。如果不可避免,请确保在完成操作后将对上下文对象的引用设置为null,以帮助减少内存泄漏的风险。
詹森·克罗斯比

1
只要可以监视活动的生命周期,传递上下文对象并不总是不好的。如果不是,那么最好使用Application上下文而不是使用getApplicationContext()的Activity上下文来避免内存泄漏。有关检索应用程序上下文的信息,请参见stackoverflow.com/questions/7144177/…
FrozenFire

14

还有一种不创建对象的方法。检查参考。感谢@cristian。下面,我添加上面参考中提到的步骤。对我来说,我不喜欢为此创建对象并进行访问。因此,我尝试getResources()不创建对象就访问。我发现了这篇文章。所以我想将其添加为答案。

请按照以下步骤通过该对象访问getResources()非活动类without passing a context

  • 创建的子类Application,例如public class App extends Application {。请参阅步骤旁边的代码。
  • 在中设置标签的android:name属性以指向您的新类,例如<application>AndroidManifest.xmlandroid:name=".App"
  • onCreate()您的应用实例的方法中,将您的上下文(例如this)保存到名为的静态字段中,app并创建一个返回此字段的静态方法(例如)getContext()
  • 现在您可以使用:App.getContext()每当您想要获取上下文时,然后我们就可以使用App.getContext().getResources()从资源中获取值。

它应该是这样的:

public class App extends Application{

    private static Context mContext;

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

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

5

这是我的答案:

public class WigetControl {
private Resources res;

public WigetControl(Resources res) 
{
    this.res = res;
}

public void setButtonDisable(Button mButton)
{
    mButton.setBackgroundColor(res.getColor(R.color.loginbutton_unclickable));
    mButton.setEnabled(false);
}

}

调用可以是这样的:

        WigetControl control = new WigetControl(getResources());
        control.setButtonDisable(btNext);


3

我们可以像这样尝试使用上下文,在父级为ViewGroup的情况下尝试。

Context context = parent.getContext();

1

完全不需要传递上下文并执行所有操作...只需执行此操作

Context context = parent.getContext();

编辑:其中父级是ViewGroup


3
我希望您因假设有一个方便的“ ViewGroup parent”成员变量而被否决。愚蠢的假设。
arnt

1

这总是对我有用:

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:
 XmlPullParser xpp = ctx.getResources().getXml(R.xml.samplexml);
 //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);

1

在Udacity的基础ANdroid课程的导游应用程序中,我使用了片段的概念。我遇到了一段时间,难以访问以字符串xml文件描述的某些字符串资源。终于得到了解决方案。

这是主要的活动课

包com.example.android.tourguidekolkata;

import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState)
{
  //lines of code
   //lines of code
    //lines of code
    YourClass adapter = new YourClass(getSupportFragmentManager(), getApplicationContext()); 
    //lines of code
    // getApplicationContext() method passses the Context of main activity to the class TourFragmentPageAdapter 
}
}

这是扩展FragmentPageAdapter的非Activity类

public class YourClass extends FragmentPagerAdapter {
private String yourStringArray[] = new String[4];
Context context;

public YourClass (FragmentManager fm, Context context)
{
    super(fm);
    this.context = context; // store the context of main activity
    // now you can use this context to access any resource 
    yourStringArray[0] = context.getResources().getString(R.string.tab1);
    yourStringArray[1] = context.getResources().getString(R.string.tab2);
    yourStringArray[2] = context.getResources().getString(R.string.tab3);
    yourStringArray[3] = context.getResources().getString(R.string.tab4);
}
@Override
public Fragment getItem(int position)
 {
 }
@Override
public int getCount() {
return 4;
}

@Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return yourStringArras[position];
}
}

0

在简单的类中声明上下文并从res文件夹中的文件获取数据

public class FileData
{
      private Context context;

        public FileData(Context current){
            this.context = current;
        }
        void  getData()
        {
        InputStream in = context.getResources().openRawResource(R.raw.file11);
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        //write stuff to get Data

        }
}

在活动类中这样声明

public class MainActivity extends AppCompatActivity 
{
 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        FileData fileData=new FileData(this);
     }

}

0

我迟到了,但是完整的解决方案;:示例类,像这样使用上下文:

public class SingletonSampleClass {

    // Your cute context
    private Context context;
    private static SingletonSampleClass instance;

  // Pass as Constructor
    private SingletonSampleClass(Context context) {
        this.context = context;
    }

    public synchronized static SingletonSampleClass getInstance(Context context) {
        if (instance == null) instance = new SingletonSampleClass(context);
        return instance;
    }

//At end, don't forgot to relase memory
    public void onDestroy() {
       if(context != null) {
          context = null; 
       }
    }
}

警告(内存泄漏)

如何解决呢?

选项1:您可以传递applicationContext()而不是将活动上下文(即活动上下文)传递给singleton类。

选项2:如果您确实必须使用活动上下文,那么在销毁活动时,请确保将传递给singleton类的上下文设置为null。

希望对您有所帮助。


0

在您的MainActivity中:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if(ResourcesHelper.resources == null){
             ResourcesHelper.resources = getResources();
        }
    }
}

ResourcesHelper:

public class ResourcesHelper {
    public static Resources resources;
}

然后到处使用

String s = ResourcesHelper.resources.getString(R.string.app_name);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.