【问题标题】:Using getResources() in non-activity class在非活动类中使用 getResources()
【发布时间】:2011-12-01 18:26:52
【问题描述】:

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

例子:

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

【问题讨论】:

标签: android android-context


【解决方案1】:

您必须将context 对象传递给它。 this 如果您在活动中有对类的引用,或者 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作为参数的地方

【讨论】:

  • 在 Android 中传递 Context 对象通常不是一个好主意。它可能导致内存泄漏。
  • 作为一个基本的经验法则,但我觉得这有点误导。 Context 对象很讨厌,因为它是应用程序范围还是活动范围的并不是很明显。当您提供错误的内存时,就会发生内存泄漏(和崩溃)。例如,将Activity 提供给需要Context 的静态对象,并且当Activity 导致Activity 在onDestroy 之后持续存在时,所述对象不会被销毁,因为由于其他原因,它无法被GC静态对象。所以是的,这可能很危险,但知道为什么我觉得这里很危险。
  • ^Dororo,这是我读过的最重要的 cmets 之一。很少讨论正确使用上下文(如果有的话)。我觉得我有很多莫名其妙的错误!
  • @Dororo 那么你有什么练习建议吗?我们应该尽量避免传递上下文变量吗?那么当我们需要activity类的一些api时,我们可以做什么呢?
  • 请注意,您可以按照此方法@Inject 资源(定义一个接受@ApplicationContext context : Context 并返回context.resources 的提供程序),这在使用数据库存储库时特别很有用,你应该已经在哪里注射了。
【解决方案2】:

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

【讨论】:

  • 这是个好建议,谢谢。在 SQLiteOpenHelper 中会出现问题吗?在构造函数中,您必须传递一个上下文。它在其他方法中不再可用,但我可以将其存储在私有字段中。
  • @Peter 是的,有些类需要您传入上下文对象。因此,最好尝试仅在活动或片段中使用像 SqLiteOpenHelper 这样的类,这样您就不必传递上下文对象。如果这是不可避免的,请确保在完成后将对上下文对象的引用设置为 null,以帮助降低内存泄漏的风险。
  • 传递上下文对象并不总是坏事,只要您可以监控活动的生命周期。如果没有,那么最好使用应用程序上下文而不是使用 getApplicationContext() 的活动上下文来避免内存泄漏。请参阅stackoverflow.com/questions/7144177/… 以获取应用程序上下文。
【解决方案3】:

还有一种不用创建对象的方法。检查reference。感谢@克里斯蒂安。下面我添加上述参考中提到的步骤。对我来说,我不喜欢为此创建一个对象并进行访问。所以我尝试在不创建对象的情况下访问getResources()。我找到了这篇文章。所以我想把它添加为答案。

按照步骤通过对象访问非活动类without passing a context中的getResources()

  • 创建Application 的子类,例如public class App extends Application {。请参阅步骤旁边的代码。
  • AndroidManifest.xml 中设置<application> 标记的android:name 属性以指向您的新类,例如android: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;
    }
}

【讨论】:

    【解决方案4】:

    这是我的答案:

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

    【讨论】:

      【解决方案5】:

      这可以通过使用来完成

      context.getResources().getXml(R.xml.samplexml);
      

      【讨论】:

      • 嗯,这对我来说很神奇。谢谢@A.R.Asha
      • 传递Context 对象不是一种健康的做法
      【解决方案6】:

      我们可以使用 context 像这样现在尝试其中的父级是 ViewGroup。

      Context context = parent.getContext();
      

      【讨论】:

        【解决方案7】:

        不需要传递上下文并做所有这些......只需这样做

        Context context = parent.getContext();
        

        编辑:其中 parent 是 ViewGroup

        【讨论】:

        • 我希望您因为假设有一个方便的“ViewGroup parent”成员变量而被否决。相当愚蠢的假设。
        【解决方案8】:

        这对我总是有效的:

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

        与此问题无关,但使用 Fragment 访问系统资源/活动的示例如下:

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

        【讨论】:

          【解决方案9】:

          在 Udacity 的 Basic ANdroid 课程的导游应用程序中,我使用了 Fragments 的概念。我遇到了一段时间难以访问字符串、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];
          }
          }
          

          【讨论】:

            【解决方案10】:

            在简单类中声明上下文并从 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
            
                    }
            }
            

            在activity类中这样声明

            public class MainActivity extends AppCompatActivity 
            {
             protected void onCreate(Bundle savedInstanceState) {
                    super.onCreate(savedInstanceState);
            
                    setContentView(R.layout.activity_main);
                    FileData fileData=new FileData(this);
                 }
            
            }
            

            【讨论】:

              【解决方案11】:

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

              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(),而不是将活动上下文(即 this)传递给单例类。

              方案二:如果你真的要使用activity上下文,那么当activity销毁时,确保你传递给单例类的上下文设置为null。

              希望对你有所帮助..ΔΔΔΔ

              【讨论】:

                【解决方案12】:

                在您的 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();
                        }
                    }
                }
                

                资源助手:

                public class ResourcesHelper {
                    public static Resources resources;
                }
                

                然后到处使用它

                String s = ResourcesHelper.resources.getString(R.string.app_name);
                

                【讨论】:

                  猜你喜欢
                  • 2015-04-05
                  • 2015-04-14
                  • 2014-09-02
                  • 2012-12-19
                  • 1970-01-01
                  • 1970-01-01
                  • 2010-12-31
                  • 2011-06-19
                  相关资源
                  最近更新 更多