비 활동 클래스에서 getResources () 사용


123

비 활동 클래스에서 getResources 메서드를 사용하려고합니다. 리소스 폴더에 저장된 xml 파일에 액세스 할 수 있도록 "리소스"개체에 대한 참조를 얻으려면 어떻게해야합니까?

예:

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

일반적으로 ContextAndroid에서 개체 를 전달하는 것은 좋은 생각이 아닙니다 . 메모리 누수로 이어질 수 있습니다. 덜 위험한 솔루션에 대한 내 대답을 참조하십시오.
Jason Crosby

답변:


147

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가 매개 변수로 받아들이는 곳


7
일반적으로 ContextAndroid에서 개체 를 전달하는 것은 좋은 생각이 아닙니다 . 메모리 누수로 이어질 수 있습니다.
Jason Crosby

28
기본적인 경험 법칙으로 확실하지만 이것은 다소 오해의 소지가 있다고 생각합니다. Context개체는 응용 프로그램 전체 또는 활동 전체인지 즉시 명확하지 않기 때문에 불쾌합니다. 잘못된 메모리를 제공하면 메모리 누수 (및 충돌)가 발생합니다. 예를 들어, Activity를 필요로하는 정적 객체에를 제공하면 이 다른 정적 객체로 인해 GCed 될 수 없기 때문에 onDestroy 이후에 지속 Context되는 Activity것으로 이어질 때 해당 객체가 파괴 Activity되지 않습니다. 그렇습니다. 위험 할 수 있지만 위험 한지 아는 것이 여기서 언급하는 것이 중요합니다.
Dororo

2
^ Dororo, 이것은 내가 읽은 가장 중요한 코멘트 중 하나입니다. 문맥의 적절한 사용은 거의 논의되지 않습니다. 나는 그것 때문에 설명 할 수없는 버그가 많다는 느낌을 받는다!
Jonathan Dunn

@Dororo 그래서 연습 제안이 있습니까? 컨텍스트 변수 전달을 피해야합니까? 그러면 액티비티 클래스에서 API가 필요할 때 무엇을 할 수 있습니까?
Alston

35

Context주위에 물건 을 전달하는 것은 좋은 생각이 아닙니다 . 이것은 종종 메모리 누수로 이어질 것입니다. 제 제안은 당신이 그것을하지 않는 것입니다. 앱의 비 활동 클래스에 컨텍스트를 전달할 필요없이 수많은 Android 앱을 만들었습니다. 더 나은 아이디어는 Activity또는 에있는 동안 액세스해야하는 리소스를 얻고 Fragment다른 클래스에서 유지하는 것입니다. 그런 다음 앱의 다른 클래스에서 해당 클래스를 사용하여 Context객체 를 전달하지 않고도 리소스에 액세스 할 수 있습니다.


이것은 좋은 조언입니다. SQLiteOpenHelper에서 문제가 될까요? 생성자에서 컨텍스트를 전달해야합니다. 다른 방법에서는 더 이상 사용할 수 없지만 개인 필드에 저장할 수 있습니다.
피터

2
@Peter 예, 컨텍스트 개체를 전달해야하는 클래스가 있습니다. 따라서 활동이나 프래그먼트에서 SqLiteOpenHelper와 같은 클래스 만 사용하여 컨텍스트 개체를 전달할 필요가 없도록하는 것이 가장 좋습니다. 피할 수없는 경우 메모리 누수 위험을 줄이기 위해 작업을 마쳤을 때 컨텍스트 개체에 대한 참조를 null로 설정했는지 확인하십시오.
Jason Crosby

1
활동의 수명주기를 모니터링 할 수있는 한 컨텍스트 개체를 전달하는 것이 항상 나쁜 것은 아닙니다. 그렇지 않은 경우 getApplicationContext ()를 사용하여 활동 컨텍스트 대신 응용 프로그램 컨텍스트를 사용하여 메모리 누수를 방지하십시오. 애플리케이션 컨텍스트를 검색하려면 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

이것은 사용하여 수행 할 수 있습니다

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

글쎄, 이것은 나를 위해 마술을했다. 감사 @ARAsha
케니 Dabiri

Context물체를 통과 하는 것은 건강한 습관이 아닙니다
Vemuri Pavan

3

컨텍스트를 사용할 수 있습니다. 지금 시도해보십시오. 부모가 ViewGroup입니다.

Context context = parent.getContext();

1

컨텍스트를 전달하고 모든 작업을 수행 할 필요가 없습니다.

Context context = parent.getContext();

편집 : 부모는 ViewGroup입니다.


3
편리한 'ViewGroup parent'멤버 변수가 있다고 가정하여 반대 투표를 받았을 것으로 예상합니다. 오히려 어리석은 가정.
arnt dec

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.