非アクティビティクラスでのgetResources()の使用


123

非アクティビティクラスでgetResourcesメソッドを使用しようとしています。「resources」オブジェクトへの参照を取得して、resourcesフォルダーに保存されているxmlファイルにアクセスするにはどうすればよいですか?

例:

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

通常Context、Androidでオブジェクトを渡すことはお勧めできません。メモリリークが発生する可能性があります。リスクの少ないソリューションについては、私の回答を参照してください。
Jason Crosby

回答:


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でオブジェクトを渡すことはお勧めできません。メモリリークが発生する可能性があります。
Jason Crosby

28
基本的な経験則としては確かですが、これは多少誤解を招くと思います。Contextオブジェクトが厄介なのは、それがアプリケーション全体であるかアクティビティ全体であるかがすぐに明らかではないためです。間違ったメモリを指定すると、メモリリーク(およびクラッシュ)が発生します。例えば、供給Activity必要静的オブジェクトにContextいつオブジェクトが破壊されない前記ActivityにリードされActivity、それは、この他の静的オブジェクトによるGCedすることができないので、onDestroy後に持続。そう、それは危険かもしれませんが、なぜそれが危険かを知ることはここで言及することが重要だと感じます。
ドロロ2014

2
^ Dororo、これは私が今まで読んだ中で最も重要なコメントの1つです。コンテキストを適切に使用することはめったにありませんが、議論されています。そのせいで不可解なバグがたくさんあるような気がします!
ジョナサンダン

@Dororoでは、練習のアドバイスはありますか?コンテキスト変数を渡さないようにすべきでしょうか?では、アクティビティクラスのAPIが必要な場合はどうすればよいでしょうか。
Alston

35

Contextオブジェクトを渡すのは良い考えではありません。これにより、メモリリークが発生することがよくあります。私の提案はあなたがそれをしないことです。アプリ内の非アクティビティクラスにコンテキストを渡さなくても、数多くのAndroidアプリを作成しました。より良いアイデアは、ActivityまたはFragmentでアクセスする必要があるリソースを取得し、別のクラスでそれを保持することです。その後、そのクラスをアプリ内の他のクラスで使用して、Contextオブジェクトを渡さなくてもリソースにアクセスできます。


これは良いアドバイスです。SQLiteOpenHelperの問題でしょうか?コンストラクターでは、コンテキストを渡す必要があります。他のメソッドでは使用できなくなりましたが、プライベートフィールドに格納できました。
ピーター

2
@Peterはい、コンテキストオブジェクトを渡す必要のあるクラスがいくつかあります。したがって、SqLiteOpenHelperのようなクラスのみをアクティビティまたはフラグメントで使用することをお勧めします。これにより、コンテキストオブジェクトを渡す必要がなくなります。やむを得ない場合は、メモリリークのリスクを減らすために、実行時にコンテキストオブジェクトへの参照をnullに設定してください。
Jason Crosby

1
アクティビティのライフサイクルを監視できる限り、コンテキストオブジェクトを渡すことは必ずしも悪いことではありません。そうでない場合は、getApplicationContext()を使用してアクティビティコンテキストの代わりにアプリケーションコンテキストを使用し、メモリリークを回避してください。アプリケーションコンテキストの取得については、stackoverflow.com / questions / 7144177 /…をご覧ください。
FrozenFire 2016年

14

オブジェクトを作成しないでもう1つ方法があります。リファレンスを確認してください。@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

これは、

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

まあ、これは私にとって魔法でした。ありがとう@ARAsha
Kenny Dabiri

Contextオブジェクトを渡すことは健全な習慣ではありません
Vemuri Pavan


1

コンテキストを渡してすべてを実行する必要はありません...単にこれを実行してください

Context context = parent.getContext();

編集:親はViewGroupです


3
便利な「ViewGroup親」メンバー変数があると仮定して反対票が投じられたと思います。むしろ愚かな仮定。
2013

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

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()を渡すことができます。

オプション2:本当にアクティビティコンテキストを使用する必要がある場合、アクティビティが破棄されるときに、シングルトンクラスに渡したコンテキストが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);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.