गैर-गतिविधि वर्ग में getResources () का उपयोग करना


123

मैं एक गैर-गतिविधि वर्ग में getResources विधि का उपयोग करने का प्रयास कर रहा हूं। मुझे "संसाधन" ऑब्जेक्ट का संदर्भ कैसे मिलता है ताकि मैं संसाधन फ़ोल्डर के तहत संग्रहीत xml फ़ाइल तक पहुंच पाऊं?

उदाहरण:

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

Contextएंड्रॉइड में वस्तुओं के आसपास से गुजरना सामान्य तौर पर अच्छा विचार नहीं है। इससे मेमोरी लीक हो सकती है। कम जोखिम वाले समाधान के लिए मेरा उत्तर देखें।
जेसन क्रॉस्बी

जवाबों:


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
Contextएंड्रॉइड में वस्तुओं के आसपास से गुजरना आम तौर पर एक अच्छा विचार नहीं है। इससे मेमोरी लीक हो सकती है।
जेसन क्रॉस्बी

28
अंगूठे के मूल नियम के रूप में, लेकिन मुझे लगता है कि यह कुछ भ्रामक है। Contextयदि यह अनुप्रयोग-व्यापी है या गतिविधि-व्यापी है, तो ऑब्जेक्ट खराब हैं क्योंकि यह तुरंत स्पष्ट नहीं है। मेमोरी लीक (और क्रैश) तब होती है जब आप गलत आपूर्ति करते हैं। उदाहरण के लिए, एक की आपूर्ति Activityके लिए एक स्थिर वस्तु है जो एक की जरूरत के लिए Contextऔर कहा कि वस्तु को नष्ट कर दिया नहीं है जब Activityहोता है Activityयह अन्य स्थिर वस्तु के कारण OnDestroy के बाद बने, क्योंकि यह GCed नहीं हो सकता। तो हाँ, यह खतरनाक हो सकता है, लेकिन यह जानना कि यह खतरनाक क्यों है मुझे लगता है कि यहाँ उल्लेख करना महत्वपूर्ण है।
डोरोरो

2
^ डोरो, यह उन सबसे महत्वपूर्ण टिप्पणियों में से एक है जो मैंने कभी पढ़ी हैं। संदर्भ का उचित उपयोग शायद ही कभी होता है, अगर चर्चा की जाए। मुझे लगता है कि मुझे इसकी वजह से कई अनुभवहीन बग मिला है!
जोनाथन डन

@ डोरो तो क्या आपके पास कोई अभ्यास सुझाव है? क्या हमें संदर्भ चर पास से बचने की कोशिश करनी चाहिए? तब तब हम क्या कर सकते हैं जब हमें एक्टिविटी क्लास से कुछ एपी की जरूरत है?
एलस्टन

35

इसके Contextआसपास वस्तुओं को पास करने के लिए एक अच्छा विचार नहीं है । इससे अक्सर मेमोरी लीक हो जाएगी। मेरा सुझाव यह है कि आप ऐसा नहीं करते हैं। मैंने ऐप में गैर-गतिविधि कक्षाओं के संदर्भ के बिना कई एंड्रॉइड ऐप बनाए हैं। एक बेहतर विचार यह होगा कि आप अपने Activityया उस समय के संसाधनों को प्राप्त कर सकें Fragmentऔर दूसरी कक्षा में उसे पकड़ सकें। फिर आप Contextऑब्जेक्ट्स के चारों ओर जाने के बिना, संसाधनों तक पहुंचने के लिए अपने एप्लिकेशन में किसी भी अन्य कक्षाओं में उस क्लास का उपयोग कर सकते हैं।


यह अच्छी सलाह है धन्यवाद। यह एक SQLiteOpenHelper में एक समस्या होगी? कंस्ट्रक्टर में, आपको एक संदर्भ पास करना होगा। यह अन्य तरीकों में उपलब्ध नहीं है, लेकिन मैं इसे एक निजी क्षेत्र में संग्रहीत कर सकता हूं।
पीटर

2
@Peter हाँ कुछ वर्ग हैं जो आपको एक संदर्भ वस्तु में पास करने की आवश्यकता है। तो इसकी पूरी कोशिश है कि आप किसी गतिविधि या खंड में SqLiteOpenHelper जैसी कक्षाओं का उपयोग करें ताकि आपको संदर्भ ऑब्जेक्ट के आसपास से गुजरना न पड़े। यदि इसका अपरिहार्य है तो सुनिश्चित करें कि आपने अपने संदर्भ को ऑब्जेक्ट ऑब्जेक्ट को शून्य करने के लिए सेट किया है जब आपका मेमोरी मेमोरी के जोखिम को कम करने में मदद करने के लिए किया गया हो।
जेसन क्रॉस्बी

1
जब तक आप गतिविधि के जीवन चक्र की निगरानी कर सकते हैं तब तक संदर्भ वस्तु हमेशा खराब नहीं होती है। यदि स्मृति रिसाव से बचने के लिए getApplicationContext () का उपयोग करते हुए गतिविधि संदर्भ के बजाय एप्लिकेशन संदर्भ का उपयोग बेहतर नहीं है। एप्लिकेशन संदर्भ प्राप्त करने के लिए stackoverflow.com/questions/7144177/… देखें ।
फ्रोजनफायर

14

एक वस्तु बनाने के बिना एक और तरीका भी है। संदर्भ की जाँच करें । @ क्रिसियन के लिए धन्यवाद। नीचे मैं उन चरणों को जोड़ता हूं जो उपरोक्त संदर्भ में वर्णित हैं। मेरे लिए मुझे उस के लिए एक ऑब्जेक्ट बनाना और एक्सेस करना पसंद नहीं है। इसलिए मैंने getResources()एक ऑब्जेक्ट बनाए बिना एक्सेस करने की कोशिश की । मुझे यह पोस्ट मिली। इसलिए मैंने इसे एक उत्तर के रूप में जोड़ना उचित समझा।

ऑब्जेक्ट के माध्यम से getResources()गैर-गतिविधि वर्ग में पहुंचने के चरणों का पालन करें without passing a context

  • Applicationउदाहरण के लिए, का उपवर्ग बनाएँ public class App extends Application {। चरणों के आगे कोड देखें।
  • अपने नए वर्ग को इंगित करने के लिए android:nameअपने <application>टैग की विशेषता सेट करें AndroidManifest.xml, जैसे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;
    }
}

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

खैर, इसने मेरे लिए जादू कर दिया। धन्यवाद @ अमर
केनी

पासिंग Contextऑब्जेक्ट एक स्वस्थ अभ्यास नहीं है
वेमुरी पावन

3

हम संदर्भ का उपयोग कर सकते हैं इस तरह की कोशिश करें कि अब माता-पिता ViewGroup है।

Context context = parent.getContext();

1

अच्छी तरह से संदर्भ पारित करने की जरूरत नहीं है और वह सब कर रही है ... बस यह करो

Context context = parent.getContext();

संपादित करें: जहां अभिभावक ViewGroup है


3
मुझे उम्मीद है कि आप यह मानने के लिए कम थे कि एक सुविधाजनक 'व्यूग्रुप माता-पिता' सदस्य चर है। बल्कि मूर्खतापूर्ण धारणा है।
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

यूडेसिटी के बेसिक एन्ड्रोइड कोर्स के टूर गाइड ऐप में मैंने फ्रेगमेंट की अवधारणा का उपयोग किया है। मैं स्ट्रिंग, 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 का विस्तार करता है

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

सरल वर्ग में संदर्भ की घोषणा करें और रेस फ़ोल्डर से फ़ाइल से डेटा प्राप्त करें

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 : गतिविधि संदर्भ के संदर्भ में अर्थात एकल वर्ग के लिए, आप आवेदन पत्र () पास कर सकते हैं।

विकल्प 2: यदि आपको वास्तव में गतिविधि संदर्भ का उपयोग करना है, तो जब गतिविधि नष्ट हो जाती है, तो सुनिश्चित करें कि आपने जो संदर्भ एकल वर्ग को दिया था, वह शून्य पर सेट है।

आशा है कि यह मदद करता है.. it


0

आपकी मुख्यता में:

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);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.