Menggunakan getResources () di kelas non-aktivitas


123

Saya mencoba menggunakan metode getResources di kelas non-aktivitas. Bagaimana cara mendapatkan referensi ke objek "sumber daya" sehingga saya dapat mengakses file xml yang disimpan di folder sumber daya?

Contoh:

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

Biasanya bukan ide yang baik untuk menyebarkan Contextobjek di Android. Ini dapat menyebabkan kebocoran memori. Lihat jawaban saya untuk solusi yang tidak terlalu berisiko.
Jason Crosby

Jawaban:


147

Anda harus memberikan contextobjek ke sana. Baik thisjika Anda memiliki referensi ke kelas dalam suatu kegiatan, ataugetApplicationContext()

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

Kemudian Anda dapat menggunakannya di konstruktor (atau menyetelnya ke variabel instance):

public class RegularClass(){
    private Context context;

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

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

Dimana konstruktor menerima Contextsebagai parameter


7
Biasanya bukan ide yang baik untuk menyebarkan Contextobjek di Android. Ini dapat menyebabkan kebocoran memori.
Jason Crosby

28
Sebagai aturan dasar, tentu saja, tetapi saya merasa ini agak menyesatkan. Contextobjek buruk karena tidak langsung terlihat jelas apakah itu untuk seluruh aplikasi atau aktivitas. Kebocoran memori (dan crash) terjadi ketika Anda salah memasukkan. Misalnya, memasok sebuah Activityke objek statis yang memerlukan objek Contextdan kata tersebut tidak akan dimusnahkan jika Activitymengarah ke Activitypersisten setelah onDestroy, karena tidak dapat digabungkan karena objek statis lainnya ini. Jadi ya, ini bisa berbahaya, tetapi mengetahui mengapa itu berbahaya saya rasa penting untuk disebutkan di sini.
Dororo

2
^ Dororo, Ini adalah salah satu komentar terpenting yang pernah saya baca. Penggunaan konteks yang tepat jarang, jika pernah, dibahas. Saya merasa saya memiliki banyak bug yang tidak bisa dijelaskan karena itu!
Jonathan Dunn

@Dororo Jadi, apakah Anda punya saran latihan? Haruskah kita mencoba menghindari melewatkan variabel konteks? Lalu apa yang bisa kita lakukan ketika kita membutuhkan api dari kelas aktivitas?
Alston

35

Bukan ide yang baik untuk menyebarkan Contextbenda-benda. Ini sering kali akan menyebabkan kebocoran memori. Saran saya adalah Anda tidak melakukannya. Saya telah membuat banyak aplikasi Android tanpa harus meneruskan konteks ke kelas non-aktivitas di aplikasi. Ide yang lebih baik adalah mendapatkan sumber daya yang Anda perlukan aksesnya saat Anda berada di Activityatau Fragment, dan menyimpannya di kelas lain. Anda kemudian dapat menggunakan kelas tersebut di kelas lain dalam aplikasi Anda untuk mengakses sumber daya, tanpa harus menyebarkan Contextobjek.


Ini saran yang bagus terima kasih. Apakah ini akan menjadi masalah di SQLiteOpenHelper? Di konstruktor, Anda harus meneruskan konteks. Ini tidak lagi tersedia di metode lain tetapi saya dapat menyimpannya di bidang pribadi.
Peter

2
@ Peter Ya, ada beberapa kelas yang mengharuskan Anda untuk meneruskan objek konteks. Jadi yang terbaik adalah mencoba hanya menggunakan kelas-kelas seperti SqLiteOpenHelper dalam aktivitas atau fragmen sehingga Anda tidak perlu meneruskan objek konteks. Jika tidak dapat dihindari, pastikan Anda menyetel referensi ke objek konteks ke null setelah selesai untuk membantu mengurangi risiko kebocoran memori.
Jason Crosby

1
Meneruskan objek konteks tidak selalu buruk, selama Anda bisa memantau siklus hidup aktivitas. Jika tidak, lebih baik gunakan konteks Aplikasi daripada konteks Aktivitas menggunakan getApplicationContext () untuk menghindari kebocoran memori. Lihat stackoverflow.com/questions/7144177/… untuk mengambil konteks aplikasi.
FrozenFire

14

Ada satu cara lagi tanpa membuat objek juga. Periksa referensi . Terima kasih untuk @cristian. Di bawah ini saya menambahkan langkah-langkah yang disebutkan dalam referensi di atas. Bagi saya, saya tidak suka membuat objek untuk itu dan akses. Jadi saya mencoba mengakses getResources()tanpa membuat objek. Saya menemukan posting ini. Jadi saya berpikir untuk menambahkannya sebagai jawaban.

Ikuti langkah-langkah untuk mengakses getResources()di kelas non aktivitas without passing a contextmelalui objek.

  • Buat subkelas Application, misalnya public class App extends Application {. Lihat kode di samping langkah-langkah tersebut.
  • Setel android:nameatribut <application>tag Anda AndroidManifest.xmlke untuk menunjuk ke kelas baru Anda, misalnyaandroid:name=".App"
  • Dalam onCreate()metode instance aplikasi Anda, simpan konteks Anda (mis. this) Ke bidang statis bernama appdan buat metode statis yang mengembalikan bidang ini, mis getContext().
  • Sekarang Anda dapat menggunakan: App.getContext()kapan pun Anda ingin mendapatkan konteks, dan kemudian kita dapat menggunakan App.getContext().getResources()untuk mendapatkan nilai dari sumber daya.

Beginilah seharusnya terlihat:

public class App extends Application{

    private static Context mContext;

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

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

5

inilah jawaban saya:

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

}

dan panggilannya bisa seperti ini:

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

3

ini bisa dilakukan dengan menggunakan

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

Nah, inilah keajaiban bagi saya. Terima kasih @ARAsha
Kenny Dabiri

melewati Contextbenda bukanlah praktik yang sehat
Vemuri Pavan

3

Kita bisa menggunakan konteks Seperti ini coba sekarang Dimana induknya adalah ViewGroup.

Context context = parent.getContext();

1

tidak perlu melewati konteks dan melakukan semua itu ... cukup lakukan ini

Context context = parent.getContext();

Edit: di mana induknya adalah ViewGroup


3
Saya berharap Anda mendapatkan suara negatif karena mengasumsikan bahwa ada variabel anggota 'ViewGroup parent' yang nyaman. Asumsi yang agak bodoh.
Bukankah

1

Ini selalu berhasil untuk saya:

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

}

Tidak terkait dengan pertanyaan ini, tetapi contoh menggunakan Fragmen untuk mengakses sumber daya / aktivitas sistem seperti ini:

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

Dalam aplikasi pemandu wisata kursus ANdroid Dasar Udacity, saya telah menggunakan konsep Fragmen. Saya terjebak untuk sementara mengalami kesulitan untuk mengakses beberapa sumber daya string yang dijelaskan dalam string, file xml. Akhirnya mendapat solusi.

Ini adalah kelas aktivitas utama

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

Ini adalah kelas non Aktivitas yang memperluas 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

Dalam kelas sederhana deklarasikan konteks dan dapatkan data dari file dari folder 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

        }
}

Di kelas aktivitas, deklarasikan seperti ini

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

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

}

0

Saya terlambat tapi solusi lengkap ;: Contoh Kelas, Gunakan Konteks seperti ini: -

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

Peringatan (Kebocoran Memori)

Bagaimana mengatasi ini?

Opsi 1 : Daripada meneruskan konteks aktivitas yaitu ini ke kelas tunggal, Anda bisa meneruskan applicationContext ().

Opsi 2: Jika Anda benar-benar harus menggunakan konteks aktivitas, maka saat aktivitas dimusnahkan, pastikan bahwa konteks yang Anda teruskan ke kelas tunggal disetel ke null.

Semoga membantu..∆∆∆∆


0

di MainActivity Anda:

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

lalu gunakan di mana saja

String s = ResourcesHelper.resources.getString(R.string.app_name);
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.