2016-11-14 61 views
0

我有一个属性文件存储在资产文件夹的Android项目。我需要在每次需要值时避免该文件的I/O读取,以便第一次加载文件并将其保存在静态字段中。请记住,这是一款在嵌入式平板电脑上“始终运行”的应用程序,因此基本上没有生命周期。这是我对本作的实现:在内存中的Android缓存属性文件,以避免I/O

Properties.java:

private static java.util.Properties properties; 
private static Context mContext; 

public static void init(Context context) { 
    mContext = context.getApplicationContext(); 
    if(properties == null){ 
     AssetManager assetManager = context.getAssets(); 
     InputStreamReader reader = null; 
     try { 
      reader = new InputStreamReader(assetManager.open("path_to_prop_file"), "UTF-8"); 
      properties = new java.util.Properties(); 
      properties.load(reader); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      try { 
       reader.close(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

public static String get(String entry){ 
    try { 
     return properties.getProperty(entry); 
    } catch (Exception e){ 
     init(mContext); 
     return properties.getProperty(entry); 
    } 
} 

然后我把它从活动:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    Properties.init(getApplicationContext()); 
    String property = Properties.get("prop_key"); 
} 

我是缓存也语境的情况下,属性文件需要被重新加载。我可以将上下文作为参数传递给“Get”方法,但是我需要在应用程序中随处读取属性,并且我不想通过所有类传递上下文。 我想知道如果这个实现是好的,并且在我的情况下关于上下文的泄漏是危险的。 任何建议被理解

EDIT 1:最后块中追加关闭读者所建议

+0

考虑关闭你的阅读器在finally块 –

+0

@NicolasFilotto当然我会感谢 – Nem3sis

回答

0

如果有关上下文泄漏发生在我的情况下

危险在泄漏方面, Application是全球单身人士。它是预泄漏的;你不能进一步泄漏它。您的Properties泄露,但这是设计。

我想知道如果这个实现是确定

你还没有解决线程。在主应用程序线程上拥有这种I/O会导致丢帧和UI结果。而且,一旦开始进入线程,您的实现将变得更加复杂以处理竞争条件(例如,代码在读取属性的线程完成执行之前想要使用属性)。

我会重温打包属性文件的想法。例如,你可以:

  • 手工编写包含这些属性

  • 位的代码添加到您的build.gradle文件,这些属性转换成在BuildConfig类字段的Java类,使用buildConfigField

  • 写小代码生成摇篮插件,你的属性转换成Java类(this book sample of mine这是否为一个简单的JSON文件)

+0

感谢@CommonsWare的回复!如果我明白了,对java.util.Properties.getProperty(String)方法的每次调用都是读入属性文件的I/O?我认为这只是InputStream执行一次I/O操作。我还会寻找Gradle解决方案来将prop转换成java类 – Nem3sis

+0

@ Nem3sis:“我认为这只是InputStream的I/O一次” - 正确。我的假设是你在主应用程序线程上使用你的get()方法。如果这总是会在后台线程上调用,那么你不会用'init()'I/O阻塞主应用程序线程,那么我的线程问题就会消失。 – CommonsWare

+0

是的,我在主线程上使用'get()'。我会在丢帧的情况下进行分析,并考虑如果情况在背景中移动。谢谢 – Nem3sis