4

バックグラウンド

できるだけモジュール化されたアプリを維持しようとしています。
アプリには、さまざまな間隔で実行するタスクがあります。私の目標は、基礎となるアーキテクチャを最小限に理解し、他のファイルを変更する必要がなく、同時にコードを過度に複雑にせずに、新しいタスクをできるだけ簡単に追加できるようにすることです。

新しいタスクを追加するために必要なことは、ファイルを作成することだけであり、それで十分です。
これには、実行時にタスクをロードする必要がありますが、これはあまり好きではありません。すべての登録が行われる単一の場所に住むことができます (これにより、タスクの切り替えも可能になりました)。

現在、すべてのタスクを登録する(基本的にリストに追加する)静的コードを含む抽象タスククラスがあります。

問題

各タスクには、独自の設定と場合によってはリソースがあります。
名前にプレフィックスを使用することで、文字列と配列を分割するのは非常に簡単ですが、主な問題は設定にあります。

現在PreferenceActivity、設定を表示するために a を使用しています。
一般設定は XML ファイルからロードされます。各タスクの設定は、個別の にありPreferenceScreenます。すべてのタスクに共通するものは 1 つだけで、それは「有効」チェックボックスです。

すべての設定を 1 つのファイルに保存したくはありません。

現在のソリューション

現在、各タスクには、setupPreferences(PreferenceScreen)必要なオプションを追加できるメソッドがあります。ただし、これにはプログラムによるという欠点がありますが、これはそれほど悪いことではありませんが、可能であれば避けたいと思います。

望ましい解決策

最適な解決策は、各タスクがロードされてルートに追加される独自の XML ファイルを持つことができる場合ですがPreferenceScreen、私が知る限り、これは不可能です。ロードする唯一の方法はPreferenceActivity.

その他の注意事項

アンドロイドでリソースを分割することについて他に提案がある場合は、自由に共有してください:)

ありがとう
ニクラス


明確化

私が話しているタスクは決してサードパーティではなく、内部のみです。これは、このアプリの優れた構造を早い段階で取得するための方法です。

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 に答える