2017-03-18 5 views
1

MainActivityのアクティビティーをフラグメントMainFragmentと考えてください。このフラグメントには、複雑なレイアウト階層があり、図書館com.framer:frame_me:1.1からのビューグループFrameがあります。フレーバー特有のコード

私は2つの味foobar、と私は、このFramebar味ではなくfooでしかないようにしたい、XML要素のJavaコードと依存を持っている場合。私はこれをどのようにするべきですか?

私は、フラグメントとそのXMLに関する

barCompile 'com.framer:frame_me:1.1' 

しかし、何を使用して依存関係をコンパイルすることができます。同じコードを2つの場所に保持したくないので、2つのバリエーションを両方のフレーバに書き込むことは望ましくありません。


一つの可能​​性のあるアイデア(おそらく悪い1)私の心の中でこのことを次のとおりです。

  1. barソースセット内の別のファイルにXML要素を移動します。同じ名前のfooソースセットにViewStub要素を追加します。このXMLファイルには、フラグメントXMLにincludeを含めるようにします。
  2. ソースセットのFrameビューを処理するインターフェイスを追加します。空の実装をfooソースセットに追加し、1つをbarソースセットに追加します。このようにして、すべてのロジックはbarのままとなりますが、すべての共通ロジックはソースセットmainに残ります。

これは、フレーバー固有のコードとxmlを書くだけで非常に多くの作業をしています。

+0

フレームのビューを拡張してmain.xmlにこのビューを表示し、フレーバで実行している場合にのみGONEを有効にするのはなぜですか? ビュー –

+0

の新しいサブクラス 'barCompile'に余分なxmlを追加することができます! 'Frame'は' foo'フレーバにも存在しません。これはエラーを投げます。または、私はあなたのコメントを正しく理解していませんでしたか? – Sourabh

+0

あなたのXMLにも依存関係が必要ですか? –

答えて

0

あなただけの抽象化を必要としています。 Rクラスの整数インデックスを使用してリソースが識別されるため、intファイルをレイアウトファイルのプレースホルダとして使用できます。アクティブなレイアウト内でレイアウト要素IDが検索された場合、共通要素をリサイクルできます。まず、すべての共通要素を持つ共通のフラグメントクラスを作成します。

public abstract class BaseFlavorFragment extends Fragment { 

/*Define an interface for whatever code the fragment may need from the outside and a member for keeping reference of that. You can also use the host activity, this is just for flexibility*/ 
    public interface whateverThisDoes{ 
     void do(); 
    } 
/*All the common fragment members go here, as protected so you can reach them from every subclass*/ 
    protected TextView title; 
    protected Button mainButton; 
    protected whateverThisDoes listener; 

    public void setWhateverThisDoes(whateverThisDoes listener){ 
     this.listener = listener; 
    } 
/*Finally, create a int variable that will hold the reference to the layout file you need to use. you will set this in every flavor using the setContainer method.*/ 
    protected int layout = 0; 

    /*this will allow you to select which XML to use 
layout = R.layout.flavorlayout*/ 
    public abstract setContainer(); 

    /*Use this method to inflate any flavor members, like the Frame you mentioned*/ 
    public abstract void inflateComponents(); 
    /*Use this to set listeners, data, or anything the flavor controls do*/ 
    public abstract void setBehaviors(); 

    /*Set here anything the common controls do*/ 
    protected void setCommonBehaviors(){ 
     button.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       //whatever     
      } 
     }); 
     setBehaviors(); 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState){ 
     super.onCreate(savedInstanceState); 
     setContainer(); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     super.onCreateView(inflater, container, savedInstanceState); 
     View view = inflater.inflate(layout, container, false); 
     /*Inflate common components*/ 
     title = (TextView) root.findViewById(R.id.title); 
     button = (Button) root.findViewById(R.id.button); 
     /*inflate flavor components, if there's any*/ 
     inflateComponents(); 
     /*assign data, listeners, whatever the flavor controls do*/ 
     setBehaviors();   
     return view; 
    } 
} 

これでFooとBarの実装を作成できます。唯一の違いがレイアウトファイルの場合は、すべてを基本クラスに入れ、setContainer()を使用してレイアウトファイルを設定します。より多くの相違点がある場合は、それぞれの抽象メソッドに対処する必要があります。基本クラスは、共通のコード、実装、それぞれの味に生きることができます。外部からビヘイビアコードを設定する必要がない場合は、インターフェイスを削除することができます。

+0

私はこのような多くの抽象メソッドではなく、単に機能を追加してビューを動的に追加する方法をオーバーライドしました。 – Sourabh

1

XMLのFrameタグをFrameLayoutコンテナに置き換えるのはどうですか?

次に、barフレーバーのソースコードでは、Frameをインスタンス化してcontainer.addView(frame)と言うことができます。 fooフレーバーはFrameクラスへの参照を持たず、コンテナを無視します。

これは、最初のアプローチに似ていますが、別個のリソースセットを維持する必要はありません。とにかく、いくつかのフレーバー固有のJavaコードがあることは合理的です。

+0

しかし、このフレーバー固有のJavaコードを、2つのフレーバーでフラグメント全体を複製せずに別々に保つにはどうすればよいですか? – Sourabh

+0

コードの一部をヘルパークラスに移動し、そのファイルを第2のフレーバにコピーして修正することができます。しかし、両方のフレーバでソースファイル全体を持たなければなりません。 –

+0

だから本質的に私が提案したものと同じだが、ちょっと違う。私はそれが唯一の方法だと思う。悲しい。 – Sourabh

0

build.gradle sourceSetsオプションについて教えてください。 あなたはバーのフォルダにフラグメントとXMLを配置し、設定できます

android { 
    productFlavors { 
     ... 
    } 
    sourceSets { 
     bar.java.srcDirs = ['src/bar/java'] 
     bar.res.srcDirs = ['src/bar/res'] 
    } 
} 
+0

ソースセットについて知っています。私の質問は、2つの味のJavaソースセットで多くのコードを複製せずにどうしたらいいですか? – Sourabh

関連する問題