Użycie metody getResources () w klasie niebędącej aktywnością
123
Próbuję użyć metody getResources w klasie niebędącej aktywnością. Jak uzyskać odwołanie do obiektu „resources”, aby uzyskać dostęp do pliku xml przechowywanego w folderze zasobów?
Zwykle nie jest dobrym pomysłem przekazywanie Contextobiektów w systemie Android. Może to prowadzić do wycieków pamięci. Zobacz moją odpowiedź na mniej ryzykowne rozwiązanie.
Podstawowa zasada jest pewna, ale uważam, że jest to nieco mylące. Contextobiekty są nieprzyjemne, ponieważ nie jest od razu oczywiste, czy obejmują one całą aplikację, czy działanie. Wycieki pamięci (i awarie) występują, gdy podasz niewłaściwy. Na przykład dostarczenie an Activitydo obiektu statycznego, który wymaga obiektu a, Contexta wspomniany obiekt nie jest niszczone, gdy Activityprowadzi do Activityutrwalenia po onDestroy, ponieważ nie można go GCed z powodu tego innego statycznego obiektu. Więc tak, może to być niebezpieczne, ale czuję , że wiedząc, dlaczego jest to niebezpieczne, warto tutaj wspomnieć.
^ Dororo, to jeden z najważniejszych komentarzy, jakie kiedykolwiek czytałem. Rzadko, jeśli w ogóle, omawia się właściwe użycie kontekstu. Mam wrażenie, że miałem przez to wiele niewytłumaczalnych błędów!
@Dororo Czy masz jakieś sugestie dotyczące ćwiczeń? Czy powinniśmy unikać przekazywania zmiennych kontekstowych? Co zatem możemy zrobić, gdy potrzebujemy interfejsu API z klasy aktywności?
Przekazywanie przedmiotów nie jest dobrym pomysłem Context. To często prowadzi do wycieków pamięci. Moja sugestia jest taka, że tego nie robisz. Zrobiłem wiele aplikacji na Androida bez konieczności przekazywania kontekstu klasom niezwiązanym z aktywnością w aplikacji. Lepszym pomysłem byłoby zdobycie zasobów, do których potrzebujesz dostępu, gdy jesteś w Activitylub Fragment, i trzymanie ich w innej klasie. Następnie możesz użyć tej klasy w innych klasach w aplikacji, aby uzyskać dostęp do zasobów bez konieczności przekazywania Contextobiektów.
To dobra rada, dzięki. Czy byłby to problem w SQLiteOpenHelper? W konstruktorze musisz przekazać kontekst. Nie jest już dostępny w innych metodach, ale mogłem go przechowywać w prywatnym polu.
@Peter Tak, istnieje kilka klas, które wymagają przekazania obiektu kontekstu. Dlatego najlepiej jest próbować używać tylko tych klas, takich jak SqLiteOpenHelper, w działaniu lub fragmencie, aby nie trzeba było przekazywać obiektu kontekstu. Jeśli jest to nieuniknione, po prostu upewnij się, że po zakończeniu ustawiłeś odwołanie do obiektu kontekstu na null, aby zmniejszyć ryzyko wycieków pamięci.
Przekazywanie obiektu kontekstu nie zawsze jest złe, o ile możesz monitorować cykl życia działania. Jeśli nie, lepiej użyj kontekstu aplikacji zamiast kontekstu działania za pomocą metody getApplicationContext (), aby uniknąć wycieków pamięci. Zobacz stackoverflow.com/questions/7144177/… w celu pobrania kontekstu aplikacji.
Jest jeszcze jeden sposób bez tworzenia obiektu. Sprawdź odniesienie . Dzięki za @cristian. Poniżej dodaję kroki, które wspomniałem w powyższym odnośniku. Ja nie lubię tworzyć obiektu do tego i dostępu. Więc próbowałem uzyskać dostęp do getResources()bez tworzenia obiektu. Znalazłem ten post. Pomyślałem więc o dodaniu tego jako odpowiedzi.
Postępuj zgodnie z instrukcjami, aby uzyskać dostęp getResources()do klasy niebędącej działaniem without passing a contextza pośrednictwem obiektu.
Utwórz podklasę Application, na przykład public class App extends Application {. Zapoznaj się z kodem obok kroków.
Ustaw android:nameatrybut swojego <application>tagu w, AndroidManifest.xmlaby wskazywał na twoją nową klasę, npandroid:name=".App"
W onCreate()metodzie Twojej instancji aplikacji zapisz kontekst (np. this) W statycznym polu o nazwie appi utwórz statyczną metodę, która zwraca to pole, np getContext().
Teraz możesz użyć: App.getContext()kiedy chcesz uzyskać kontekst, a następnie możemy użyć App.getContext().getResources()do pobrania wartości z zasobów.
W aplikacji przewodnika kursu Basic ANdroid Udacity wykorzystałem koncepcję fragmentów. Utknąłem na chwilę, mając trudności z dostępem do niektórych zasobów ciągu opisanych w ciągach znaków, pliku xml. Wreszcie znalazłem rozwiązanie.
To jest główna klasa aktywności
pakiet 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;publicclassMainActivityextendsAppCompatActivity{@Overrideprotectedvoid onCreate(Bundle savedInstanceState){//lines of code//lines of code//lines of codeYourClass adapter =newYourClass(getSupportFragmentManager(), getApplicationContext());//lines of code// getApplicationContext() method passses the Context of main activity to the class TourFragmentPageAdapter }}
To jest klasa non Activity, która rozszerza FragmentPageAdapter
publicclassYourClassextendsFragmentPagerAdapter{privateString yourStringArray[]=newString[4];Context context;publicYourClass(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);}@OverridepublicFragment getItem(int position){}@Overridepublicint getCount(){return4;}@OverridepublicCharSequence getPageTitle(int position){// Generate title based on item positionreturn yourStringArras[position];}}
Jestem spóźniony, ale kompletne rozwiązanie;: Przykładowa klasa, użyj kontekstu w następujący sposób: -
publicclassSingletonSampleClass{// Your cute contextprivateContext context;privatestaticSingletonSampleClass instance;// Pass as ConstructorprivateSingletonSampleClass(Context context){this.context = context;}publicsynchronizedstaticSingletonSampleClass getInstance(Context context){if(instance ==null) instance =newSingletonSampleClass(context);return instance;}//At end, don't forgot to relase memorypublicvoid onDestroy(){if(context !=null){
context =null;}}}
Ostrzeżenie (wycieki pamięci)
Jak to rozwiązać?
Opcja 1 : Zamiast przekazywać kontekst działania, czyli to do klasy pojedynczej, możesz przekazać applicationContext ().
Opcja 2: Jeśli naprawdę musisz użyć kontekstu działania, po zniszczeniu działania upewnij się, że kontekst przekazany do klasy pojedynczej ma wartość null.
Używamy plików cookie i innych technologii śledzenia w celu poprawy komfortu przeglądania naszej witryny, aby wyświetlać spersonalizowane treści i ukierunkowane reklamy, analizować ruch w naszej witrynie, i zrozumieć, skąd pochodzą nasi goście.
Kontynuując, wyrażasz zgodę na korzystanie z plików cookie i innych technologii śledzenia oraz potwierdzasz, że masz co najmniej 16 lat lub zgodę rodzica lub opiekuna.
Context
obiektów w systemie Android. Może to prowadzić do wycieków pamięci. Zobacz moją odpowiedź na mniej ryzykowne rozwiązanie.