ฉันพยายามใช้เมธอด getResources ในคลาสที่ไม่ใช่กิจกรรม ฉันจะได้รับการอ้างอิงไปยังวัตถุ "ทรัพยากร" เพื่อให้สามารถเข้าถึงไฟล์ xml ที่เก็บไว้ในโฟลเดอร์ทรัพยากรได้อย่างไร
ตัวอย่าง:
XmlPullParser xpp = getResources().getXml(R.xml.samplexml);
ฉันพยายามใช้เมธอด getResources ในคลาสที่ไม่ใช่กิจกรรม ฉันจะได้รับการอ้างอิงไปยังวัตถุ "ทรัพยากร" เพื่อให้สามารถเข้าถึงไฟล์ xml ที่เก็บไว้ในโฟลเดอร์ทรัพยากรได้อย่างไร
ตัวอย่าง:
XmlPullParser xpp = getResources().getXml(R.xml.samplexml);
คำตอบ:
คุณจะต้องส่งผ่าน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
เป็นพารามิเตอร์
Context
วัตถุต่างๆใน Android อาจนำไปสู่การรั่วไหลของหน่วยความจำ
Context
วัตถุเป็นสิ่งที่น่ารังเกียจเนื่องจากไม่สามารถมองเห็นได้ชัดเจนในทันทีว่าเป็นแอปพลิเคชันทั้งแบบกว้างหรือทั่วทั้งกิจกรรม หน่วยความจำรั่ว (และล่ม) เกิดขึ้นเมื่อคุณใส่ผิด ตัวอย่างเช่นการจัดหาActivity
วัตถุให้กับวัตถุคงที่ซึ่งต้องการContext
และกล่าวว่าวัตถุจะไม่ถูกทำลายเมื่อActivity
นำไปสู่การActivity
คงอยู่หลังจาก onDestroy เนื่องจากไม่สามารถ GCed ได้เนื่องจากวัตถุคงที่อื่นนี้ ใช่มันอาจเป็นอันตรายได้ แต่เมื่อรู้ว่าทำไมจึงอันตรายฉันรู้สึกว่าเป็นเรื่องสำคัญที่จะต้องพูดถึงที่นี่
ไม่ใช่ความคิดที่ดีที่จะส่งContext
สิ่งของไปรอบ ๆ ซึ่งมักจะนำไปสู่การรั่วไหลของหน่วยความจำ ข้อเสนอแนะของฉันคืออย่าทำ ฉันสร้างแอพ Android มากมายโดยไม่ต้องส่งบริบทไปยังคลาสที่ไม่ใช่กิจกรรมในแอพ แนวคิดที่ดีกว่าคือการได้รับทรัพยากรที่คุณต้องการเข้าถึงในขณะที่คุณอยู่ในActivity
หรือFragment
และเก็บไว้ในชั้นเรียนอื่น จากนั้นคุณสามารถใช้คลาสนั้นในคลาสอื่น ๆ ในแอพของคุณเพื่อเข้าถึงทรัพยากรโดยไม่ต้องผ่านContext
วัตถุ
มีอีกวิธีหนึ่งโดยไม่ต้องสร้างวัตถุด้วย ตรวจสอบการอ้างอิง ขอบคุณสำหรับ @cristian ด้านล่างฉันเพิ่มขั้นตอนที่กล่าวถึงในข้อมูลอ้างอิงข้างต้น สำหรับฉันฉันไม่ต้องการสร้างวัตถุสำหรับสิ่งนั้นและเข้าถึง ดังนั้นฉันจึงพยายามเข้าถึงgetResources()
โดยไม่ต้องสร้างวัตถุ เจอกระทู้นี้ เลยคิดว่าจะเพิ่มเป็นคำตอบ
ทำตามขั้นตอนเพื่อเข้าถึงgetResources()
ในคลาสที่ไม่ใช่กิจกรรมwithout passing a context
ผ่านอ็อบเจ็กต์
Application
public class App extends Application {
อ้างอิงรหัสถัดจากขั้นตอนandroid:name
แอตทริบิวต์ของ<application>
แท็กของคุณในAndroidManifest.xml
to ชี้ไปที่คลาสใหม่ของคุณเช่น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;
}
}
นี่คือคำตอบของฉัน:
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);
ซึ่งสามารถทำได้โดยใช้
context.getResources().getXml(R.xml.samplexml);
Context
วัตถุไม่ใช่แนวทางปฏิบัติที่ดีต่อสุขภาพ
เราสามารถใช้บริบทเช่นนี้ลองตอนนี้โดยที่ผู้ปกครองคือ ViewGroup
Context context = parent.getContext();
ไม่จำเป็นต้องผ่านบริบทและทำทุกอย่าง ... เพียงแค่ทำสิ่งนี้
Context context = parent.getContext();
แก้ไข: โดยที่พาเรนต์คือ ViewGroup
สิ่งนี้ใช้ได้กับฉันเสมอ:
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...
}
ไม่เกี่ยวข้องกับคำถามนี้ แต่เป็นตัวอย่างการใช้ Fragment เพื่อเข้าถึงทรัพยากรระบบ / กิจกรรมเช่นนี้:
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);
ในแอพไกด์นำเที่ยวของหลักสูตร Basic ANdroid ของ Udacity ฉันได้ใช้แนวคิดของ 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
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];
}
}
ในคลาสธรรมดาให้ประกาศบริบทและรับข้อมูลจากไฟล์จากโฟลเดอร์ 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);
}
}
ฉันมาช้า แต่วิธีแก้ปัญหาที่สมบูรณ์: ตัวอย่างคลาสใช้บริบทเช่นนี้: -
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 : แทนที่จะส่งบริบทกิจกรรมเช่นนี้ไปยังคลาส singleton คุณสามารถส่ง applicationContext () ได้
ตัวเลือกที่ 2:หากคุณต้องใช้บริบทกิจกรรมจริงๆเมื่อกิจกรรมถูกทำลายตรวจสอบให้แน่ใจว่าบริบทที่คุณส่งไปยังคลาสซิงเกิลตันถูกตั้งค่าเป็นโมฆะ
หวังว่าจะช่วยได้ .. ∆∆∆∆
ใน 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();
}
}
}
ทรัพยากร
public class ResourcesHelper {
public static Resources resources;
}
จากนั้นใช้งานได้ทุกที่
String s = ResourcesHelper.resources.getString(R.string.app_name);
Context
วัตถุต่างๆใน Android อาจนำไปสู่การรั่วไหลของหน่วยความจำ ดูคำตอบของฉันสำหรับวิธีแก้ปัญหาที่มีความเสี่ยงน้อย