4

背景

我试图保留一个尽可能模块化的应用程序。
该应用程序将具有在不同时间间隔执行的任务。我的目标是在对底层架构了解最少的情况下尽可能轻松地添加新任务,并且无需修改其他文件,但同时又不会使代码过于复杂。

如果添加新任务所需要做的就是创建文件,那将是完美的。
这将需要在运行时加载我不太喜欢的任务,我可以住在一个完成所有注册的地方(这也启用了任务的切换)

现在我有一个抽象任务类,它有一段静态代码,用于注册所有任务(基本上将它们添加到列表中)。

问题

每个任务都有自己的一组偏好和可能的资源。
通过使用名称前缀来划分字符串和数组非常容易,但主要问题在于首选项。

现在我正在使用 aPreferenceActivity来显示我的偏好。
常规设置从 XML 文件加载。每个任务的首选项位于单独的PreferenceScreen. 所有任务只有一个共同点,那就是“启用”复选框。

我不想将所有首选项存储在一个文件中,因为这样可能会变得非常混乱。

当前解决方案

现在每个任务都有一个方法setupPreferences(PreferenceScreen),他们可以在其中添加他们想要的任何选项。然而,这有以编程方式进行的缺点,这并不是那么糟糕,但如果可能的话,我想避免这种情况。

所需的解决方案

最佳解决方案是,如果每个任务都可以拥有自己的 XML 文件,该文件被加载并添加到 rootPreferenceScreen中,据我所知这是不可能的,加载它的唯一方法是加载到PreferenceActivity.

其他注意事项

如果有人对在android中划分资源有任何其他建议,请随时分享:)

谢谢尼克拉斯
_


澄清

我所说的任务绝不是第三方的,它们只会在内部进行。这更像是早期获得此应用程序良好结构的一种方式。

4

2 回答 2

3

通过使用反射,我调用从我的 XML 文件PreferenceManager.inflateFromResource(Context, int, PreferenceScreen)创建一个。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到根的底部。

于 2011-06-17T19:32:57.033 回答
0

不完全是您问题的答案,但无论如何可能会很有趣:查看用于 Locale 和 Tasker 的插件 API:http: //www.twofortyfouram.com/developer.html

Locale 和 Tasker 是电话自动化应用程序。两者都是高度可配置和模块化的,它们接受第三方插件来扩展其功能。与您的情况类似,每个插件都有独特的偏好。他们对问题的解决方案是,每个插件都有自己的偏好活动,可以使用特定的意图操作进行访问。有 UI 指南,以便首选项屏幕看起来一致。

于 2011-06-09T20:16:05.987 回答