ฉันต้องการอ่านสตริงจากxml
ไฟล์ก่อนที่ฉันจะทำอะไรอื่น ๆ อีกมากมายเช่นsetText
ในวิดเจ็ตดังนั้นฉันจะทำสิ่งนั้นโดยไม่ต้องเรียกใช้ออบเจ็กต์กิจกรรมได้getResources()
อย่างไร
ฉันต้องการอ่านสตริงจากxml
ไฟล์ก่อนที่ฉันจะทำอะไรอื่น ๆ อีกมากมายเช่นsetText
ในวิดเจ็ตดังนั้นฉันจะทำสิ่งนั้นโดยไม่ต้องเรียกใช้ออบเจ็กต์กิจกรรมได้getResources()
อย่างไร
คำตอบ:
Application
เช่นpublic class App extends Application {
android:name
แอตทริบิวต์ของ<application>
แท็กของคุณในAndroidManifest.xml
เพื่อชี้ไปที่คลาสใหม่ของคุณเช่นandroid:name=".App"
onCreate()
วิธีการของแอปอินสแตนซ์ของคุณให้บันทึกบริบท (เช่นthis
) ไปยังฟิลด์สแตติกที่ตั้งชื่อmContext
และสร้างวิธีสแตติกที่ส่งคืนฟิลด์นี้เช่นgetContext()
:นี่คือลักษณะที่ควร:
public class App extends Application{
private static Context mContext;
@Override
public void onCreate() {
super.onCreate();
mContext = this;
}
public static Context getContext(){
return mContext;
}
}
ตอนนี้คุณสามารถใช้: App.getContext()
เมื่อใดก็ตามที่คุณต้องการรับบริบทแล้วgetResources()
(หรือApp.getContext().getResources()
)
สำหรับทรัพยากรระบบเท่านั้น!
ใช้
Resources.getSystem().getString(android.R.string.cancel)
คุณสามารถใช้งานได้ทุกที่ในแอปพลิเคชันของคุณแม้ในการประกาศค่าคงที่แบบคงที่!
Toast
ตัวอย่างเช่นรับSharedPreference
อินสแตนซ์เปิดฐานข้อมูลตามที่ครูภาษาละตินของฉันพูดว่า: et cetera )
โซลูชัน Kotlin ของฉันคือการใช้บริบทแอปพลิเคชันแบบคงที่:
class App : Application() {
companion object {
lateinit var instance: App private set
}
override fun onCreate() {
super.onCreate()
instance = this
}
}
และคลาส Strings ที่ฉันใช้ทุกที่:
object Strings {
fun get(@StringRes stringRes: Int, vararg formatArgs: Any = emptyArray()): String {
return App.instance.getString(stringRes, *formatArgs)
}
}
ดังนั้นคุณสามารถมีวิธีที่สะอาดในการรับสตริงรีซอร์ส
Strings.get(R.string.some_string)
Strings.get(R.string.some_string_with_arguments, "Some argument")
โปรดอย่าลบคำตอบนี้ให้ฉันเก็บไว้
Strings
ก็มีประโยชน์
นอกจากนี้ยังมีความเป็นไปได้อีกอย่าง ฉันโหลด OpenGl shaders จากแหล่งข้อมูลเช่นนี้:
static private String vertexShaderCode;
static private String fragmentShaderCode;
static {
vertexShaderCode = readResourceAsString("/res/raw/vertex_shader.glsl");
fragmentShaderCode = readResourceAsString("/res/raw/fragment_shader.glsl");
}
private static String readResourceAsString(String path) {
Exception innerException;
Class<? extends FloorPlanRenderer> aClass = FloorPlanRenderer.class;
InputStream inputStream = aClass.getResourceAsStream(path);
byte[] bytes;
try {
bytes = new byte[inputStream.available()];
inputStream.read(bytes);
return new String(bytes);
} catch (IOException e) {
e.printStackTrace();
innerException = e;
}
throw new RuntimeException("Cannot load shader code from resources.", innerException);
}
อย่างที่คุณเห็นคุณสามารถเข้าถึงทรัพยากรใด ๆ ในเส้นทาง/res/...
เปลี่ยนaClass
เป็นชั้นเรียนของคุณ นี่คือวิธีที่ฉันโหลดทรัพยากรในการทดสอบ (androidTests)
The Singleton:
package com.domain.packagename;
import android.content.Context;
/**
* Created by Versa on 10.09.15.
*/
public class ApplicationContextSingleton {
private static PrefsContextSingleton mInstance;
private Context context;
public static ApplicationContextSingleton getInstance() {
if (mInstance == null) mInstance = getSync();
return mInstance;
}
private static synchronized ApplicationContextSingleton getSync() {
if (mInstance == null) mInstance = new PrefsContextSingleton();
return mInstance;
}
public void initialize(Context context) {
this.context = context;
}
public Context getApplicationContext() {
return context;
}
}
เริ่มต้น Singleton ในApplication
คลาสย่อยของคุณ:
package com.domain.packagename;
import android.app.Application;
/**
* Created by Versa on 25.08.15.
*/
public class mApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
ApplicationContextSingleton.getInstance().initialize(this);
}
}
หากฉันไม่ผิดมันทำให้คุณมีแอพพลิเคชั่นคอนเทนท์ได้ทุกที่เรียกมันด้วย ApplicationContextSingleton.getInstance.getApplicationContext();
คุณไม่จำเป็นต้องล้างข้อมูล ณ จุดใด ๆ เช่นเมื่อปิดแอปพลิเคชัน
อย่าลืมอัปเดตAndroidManifest.xml
เพื่อใช้Application
คลาสย่อยนี้:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.domain.packagename"
>
<application
android:allowBackup="true"
android:name=".mApplication" <!-- This is the important line -->
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:icon="@drawable/app_icon"
>
ตอนนี้คุณควรจะสามารถใช้ ApplicationContextSingleton.getInstance (). getApplicationContext (). getResources () จากที่ใดก็ได้นอกจากนี้ยังมีสถานที่น้อยมากที่ซับคลาสของแอปพลิเคชันไม่สามารถทำได้
โปรดแจ้งให้เราทราบหากคุณเห็นสิ่งผิดปกติที่นี่ขอบคุณ :)
ทางออกอื่น:
หากคุณมีคลาสย่อยแบบสแตติกในคลาสภายนอกแบบไม่คงที่คุณสามารถเข้าถึงทรัพยากรจากภายในคลาสย่อยผ่านตัวแปรสแตติกในคลาสภายนอกซึ่งคุณเริ่มต้นในการสร้างคลาสภายนอก ชอบ
public class Outerclass {
static String resource1
public onCreate() {
resource1 = getString(R.string.text);
}
public static class Innerclass {
public StringGetter (int num) {
return resource1;
}
}
}
ฉันใช้มันสำหรับฟังก์ชั่น getPageTitle (ตำแหน่ง int) ของ Static FragmentPagerAdapter ภายใน FragmentActivity ของฉันซึ่งมีประโยชน์เพราะ I8N
ฉันใช้App.getRes()
แทนApp.getContext().getResources()
(ตามที่ @Cristian ตอบ)
มันง่ายมากที่จะใช้ทุกที่ในรหัสของคุณ!
ดังนั้นนี่คือทางออกที่ไม่เหมือนใครซึ่งคุณสามารถเข้าถึงทรัพยากรได้จากทุกที่Util class
โดยที่คุณสามารถเข้าถึงแหล่งข้อมูลได้จากทุกที่เช่น
(1) สร้างหรือแก้ไขApplication
ชั้นเรียนของคุณ
import android.app.Application;
import android.content.res.Resources;
public class App extends Application {
private static App mInstance;
private static Resources res;
@Override
public void onCreate() {
super.onCreate();
mInstance = this;
res = getResources();
}
public static App getInstance() {
return mInstance;
}
public static Resources getResourses() {
return res;
}
}
(2) เพิ่มฟิลด์ชื่อในmanifest.xml
<application
แท็กของคุณ (หรือข้ามสิ่งนี้หากมีอยู่แล้ว)
<application
android:name=".App"
...
>
...
</application>
ตอนนี้คุณก็พร้อมแล้ว
App.getRes().getString(R.string.some_id)
ที่ใดก็ได้ในรหัสฉันคิดว่าเป็นไปได้มากขึ้น แต่บางครั้งฉันใช้วิธีนี้ (เต็มโลก):
import android.content.Context;
import <your package>.R;
public class XmlVar {
private XmlVar() {
}
private static String _write_success;
public static String write_success() {
return _write_success;
}
public static void Init(Context c) {
_write_success = c.getResources().getString(R.string.write_success);
}
}
//After activity created:
cont = this.getApplicationContext();
XmlVar.Init(cont);
//And use everywhere
XmlVar.write_success();
ฉันโหลด shader สำหรับ openGL ES จากฟังก์ชั่นคงที่
จำไว้ว่าคุณต้องใช้ตัวพิมพ์เล็กสำหรับชื่อไฟล์และไดเรกทอรีมิฉะนั้นการดำเนินการจะล้มเหลว
public class MyGLRenderer implements GLSurfaceView.Renderer {
...
public static int loadShader() {
// Read file as input stream
InputStream inputStream = MyGLRenderer.class.getResourceAsStream("/res/raw/vertex_shader.txt");
// Convert input stream to string
Scanner s = new Scanner(inputStream).useDelimiter("\\A");
String shaderCode = s.hasNext() ? s.next() : "";
}
...
}
public Static Resources mResources;
@Override
public void onCreate()
{
mResources = getResources();
}
ฉันใช้ API ระดับ 27 และพบทางออกที่ดีที่สุดหลังจากดิ้นรนเป็นเวลาประมาณสองวัน หากคุณต้องการอ่านไฟล์ xml จากคลาสที่ไม่ได้มาจากกิจกรรมหรือแอปพลิเคชันให้ทำดังต่อไปนี้
วางไฟล์ testdata.xml ไว้ในไดเรกทอรีสินทรัพย์
เขียนรหัสต่อไปนี้เพื่อรับเอกสาร testdata แยกวิเคราะห์
InputStream inputStream = this.getClass().getResourceAsStream("/assets/testdata.xml");
// create a new DocumentBuilderFactory
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// use the factory to create a documentbuilder
DocumentBuilder builder = factory.newDocumentBuilder();
// create a new document from input stream
Document doc = builder.parse(inputStream);
ในชั้นเรียนของคุณที่คุณใช้ฟังก์ชั่นแบบคงที่คุณสามารถเรียกวิธีการส่วนตัว \ สาธารณะจากชั้นนี้ ส่วนตัว \ วิธีประชาชนสามารถเข้าถึงgetResources
ตัวอย่างเช่น:
public class Text {
public static void setColor(EditText et) {
et.resetColor(); // it works
// ERROR
et.setTextColor(getResources().getColor(R.color.Black)); // ERROR
}
// set the color to be black when reset
private void resetColor() {
setTextColor(getResources().getColor(R.color.Black));
}
}
และจาก class \ activity อื่น ๆ คุณสามารถโทร:
Text.setColor('some EditText you initialized');
ถ้าคุณมีบริบทผมหมายถึงข้างใน
public void onReceive(Context context, Intent intent){
}
คุณสามารถใช้รหัสนี้เพื่อรับทรัพยากร:
context.getResources().getString(R.string.app_name);