我正在努力保留一个尽可能模块化的应用程序 该应用程序将具有不同时间间隔执行的任务。我的目标是尽可能简单地添加新任务,同时对底层架构的理解最少,而不必修改其他文件,但同时又不会使代码复杂化。
如果要添加新任务所需要做的就是创建文件,那将是完美的。 这将需要在运行时加载我不喜欢的任务,我可以住在一个完成所有注册的地方(这也可以切换任务)
现在我有一个抽象的任务类,它有一段静态代码,用于记录所有任务(基本上将它们添加到列表中)。
每项任务都有自己的首选项和可能的资源 通过使用名称的前缀来划分字符串和数组非常简单,但主要问题是首选项。
现在我正在使用PreferenceActivity
来显示我的偏好
常规设置从XML文件加载。每个任务的首选项都位于单独的PreferenceScreen
中。所有任务只有一个共同点,那就是“启用”复选框。
我不想将所有首选项存储在一个文件中,因为它可能会变得非常混乱。
现在每个任务都有一个方法setupPreferences(PreferenceScreen)
,他们可以在其中添加他们想要的任何选项。然而,这具有以编程方式存在的缺点,这并不是那么糟糕但我希望尽可能避免这种情况。
最佳解决方案是,如果每个任务都有自己的XML文件加载并添加到根PreferenceScreen
,据我所知,但这是不可能的,加载它的唯一方法是PreferenceActivity
。
如果有人对android中的资源划分有任何其他建议,请随时分享:)
感谢
尼克拉斯
我所谈论的任务从来都不是第三方,他们只会在内部。这是一个早期获得这个应用程序的良好结构的方法。
答案 0 :(得分:3)
通过使用反射,我正在调用PreferenceManager.inflateFromResource(Context, int, PreferenceScreen)
从我的XML文件中创建PreferenceScreen
。
字符串资源在单独的文件中分隔,并以taskname_
以下是用于对PreferenceScreen
进行充气的代码,它应该放在PreferenceActivity
中:
/**
* Inflates a {@link android.preference.PreferenceScreen PreferenceScreen} from the specified
* resource.<br>
* <br>
* The resource should come from {@code R.xml}
*
* @param resId The ID of the XML file
* @return The preference screen or null on failure.
*/
private PreferenceScreen inflatePreferenceScreenFromResource(int resId) {
try {
Class<PreferenceManager> cls = PreferenceManager.class;
Method method = cls.getDeclaredMethod("inflateFromResource", Context.class, int.class, PreferenceScreen.class);
return (PreferenceScreen) method.invoke(getPreferenceManager(), this, resId, null);
} catch(Exception e) {
Log.w(LOG_TAG, "Could not inflate preference screen from XML", e);
}
return null;
}
以下是如何使用它的示例:
package com.example;
import java.lang.reflect.Method;
import com.example.R;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.util.Log;
public class ExamplePreferenceActivity extends PreferenceActivity {
public static final String PREFERENCE_NAME = "ExamplePreferences";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Sets the preference name
PreferenceManager pm = getPreferenceManager();
pm.setSharedPreferencesName(PREFERENCE_NAME);
// Adds default values and the root preference screen
PreferenceManager.setDefaultValues(this, PREFERENCE_NAME, MODE_PRIVATE, R.xml.preferences_layout, false);
addPreferencesFromResource(R.xml.preferences_layout);
PreferenceScreen root = getPreferenceScreen();
// Includes R.xml.other_preferences_layout and adds it to the bottom of the root preference screen
PreferenceScreen otherPreferenceScreen = inflatePreferenceScreenFromResource(R.xml.other_preferences_layout);
root.addPreference(otherPreferenceScreen);
PreferenceManager.setDefaultValues(this, PREFERENCE_NAME, MODE_PRIVATE, R.xml.other_preferences_layout, false);
}
/**
* Inflates a {@link android.preference.PreferenceScreen PreferenceScreen} from the specified
* resource.<br>
* <br>
* The resource should come from {@code R.xml}
*
* @param resId The ID of the XML file
* @return The preference screen or null on failure.
*/
private PreferenceScreen inflatePreferenceScreenFromResource(int resId) {
try {
Class<PreferenceManager> cls = PreferenceManager.class;
Method method = cls.getDeclaredMethod("inflateFromResource", Context.class, int.class, PreferenceScreen.class);
return (PreferenceScreen) method.invoke(getPreferenceManager(), this, resId, null);
} catch(Exception e) {
Log.w(LOG_TAG, "Could not inflate preference screen from XML", e);
}
return null;
}
}
此示例将使用res/xml/preferences_layout.xml
作为根,然后将res/xml/other_preferences_layout.xml
添加到根的底部。
答案 1 :(得分:0)
不完全是您问题的答案,但无论如何都可能很有趣:查看Locale和Tasker的插件API:http://www.twofortyfouram.com/developer.html
Locale和Tasker是手机自动化应用。两者都是高度可配置和模块化的,它们接受第三方插件来扩展其功能。与您的情况类似,每个插件都有独特的偏好。他们解决问题的方法是,每个插件都带有自己的首选项活动,可以使用特定的意图操作进行访问。有UI指南,以便首选项屏幕看起来一致。