2016-08-21 9 views
0

Parcelableリスナを提供するDialogFragmentがあるため、ユーザがボタンをクリックしてダイアログを閉じるときに呼び出し元がコールバックを受け取ることができます(Parcelable)引数Bundleに格納されます)。パーサブルリスナを宣言するときのインターフェイスとスタティック抽象クラス

最初は、私はこのように、interfaceとしてそれを宣言:

public class EditTrackDialogFragment extends AppCompatDialogFragment { 

    public interface OnEditTrackDialogListener extends Parcelable{ 
     public abstract void onSave(TrackData trackData); 
     public abstract void onCancel(TrackData trackData); 
    } 

    // ... 

} 

...そして、このようにそれを実装:

public class MainActivity extends AppCompatActivity { 

    // ... 

    private EditTrackDialogFragment.OnEditTrackDialogListener onEditTrackDialogListener = new EditTrackDialogFragment.OnEditTrackDialogListener() { 
     @Override 
     public int describeContents() { 
      return 0; 
     } 

     @Override 
     public void writeToParcel(Parcel dest, int flags) { 

     } 

     @Override 
     public void onSave(TrackData trackData) { 
      Log.v(TAG, "Track saved"); 
     } 

     @Override 
     public void onCancel(TrackData trackData) { 
      Log.v(TAG, "Edit cancelled"); 
     } 
    }; 

} 

しかし、私はそれがちょうどいないようでしたと思いましたインスタンシエーターはParcelableインターフェースの実装に対処する必要があります。だから私はこのように、Parcelable自体を実装する抽象クラスとしてリスナーを宣言しようとした:

public class EditTrackDialogFragment extends AppCompatDialogFragment { 

    public static abstract class OnEditTrackDialogListener implements Parcelable{ 
     public abstract void onSave(TrackData trackData); 
     public abstract void onCancel(TrackData trackData); 

     public OnEditTrackDialogListener() { 

     } 

     protected OnEditTrackDialogListener(Parcel in) { 
     } 

     @Override 
     public void writeToParcel(Parcel dest, int flags) { 
     } 

     @Override 
     public int describeContents() { 
      return 0; 
     } 
    } 

    // ... 

} 

...と、このような具体的な実装を提供する:私の意見で

public class MainActivity extends AppCompatActivity { 

    // ... 

    private EditTrackDialogFragment.OnEditTrackDialogListener onEditTrackDialogListener = new EditTrackDialogFragment.OnEditTrackDialogListener() { 
     @Override 
     public void onSave(TrackData trackData) { 
      Log.v(TAG, "Track saved"); 
     } 

     @Override 
     public void onCancel(TrackData trackData) { 
      Log.v(TAG, "Edit cancelled"); 
     } 
    }; 

} 

これがずっとありますより洗練されており、リスナーの「インターフェイス」を提供するDialogFragmentParcelableの実装を処理する必要があるということがより論理的であると感じています。それ以外の場合は、リスナーを実装するたびにそれらの実装を提供する必要があります。リスナーは常に同じであるため、愚かなように見えます。

とにかく、私の質問はどのアプローチが「ベストプラクティス」ですか?私が掘り下げたすべての答えは、最初のアプローチに固執しているようですが、(私の意見では「より良い」)第2のアプローチと一緒にならない理由はありますか?

答えて

0

一つのこと:あなたが継承したクラスの多くを作成した場合、あなたはまだ私の意見では、あなたのアプローチをCREATOR :)

を必要とするので、あなたが抽象クラスから継承する場合は、Parcelable実装を取り除くません

抽象parcelableからあなたの時間を惜しま可能性 - 私はいくつかの抽象parcelables

を作成し、オブジェクト指向言語の目標の一つは、再利用する:)

と私はあまり仕事をしているのが好き

私は鉱山からの例をあなたと共有することができます

https://gist.github.com/c3ph3us/496d82751de74cae46f6d2aad2f11e71

はあなたのか?それはそのままでうまくいくようです。また、この回答へのコメントでは、作成者がインターフェースに必要ないと言います。メンバー変数が含まれていない抽象リスナークラスにはまだ必要ですか? - BadCash

クリエーターとの抽象的なparcelableの実装例:

https://gist.github.com/c3ph3us/1ca07c497492b322bf02d01906796471

YES - あなたは抽象クラスの実装でクリエーターを提供する必要が

public interface Parcelable { 

... 

/** 
* Interface that must be implemented and provided as a public CREATOR 
* field that generates instances of your Parcelable class from a Parcel. 
*/ 
public interface Creator<T> { 
    /** 
    * Create a new instance of the Parcelable class, instantiating it 
    * from the given Parcel whose data had previously been written by 
    * {@link Parcelable#writeToParcel Parcelable.writeToParcel()}. 
    * 
    * @param source The Parcel to read the object's data from. 
    * @return Returns a new instance of the Parcelable class. 
    */ 
    public T createFromParcel(Parcel source); 

    /** 
    * Create a new array of the Parcelable class. 
    * 
    * @param size Size of the array. 
    * @return Returns an array of the Parcelable class, with every entry 
    * initialized to null. 
    */ 
    public T[] newArray(int size); 
} 

あなたは理由を説明することができます私はCreatorインターフェイスを実装する必要がありますか?それはそれなしで完璧に動作するようですか? - BadCash

https://developer.android.com/reference/android/os/Parcelable.html https://developer.android.com/reference/android/os/Parcelable.Creator.html

嘆願は、いくつかの研究を行う:)これを試してみて、あなたがそれを行うことができれば:)作成者なしで私にヒントを与える

public class ClassC implements Parcelable { 
    // no CREATOR 

    String test 

    public ClassC(Parcel parcel) { 
     test = parcel.readString(); 
    } 

    @Override 
    public void writeToParcel(Parcel dest, int flags) { 
     dest.writeString(test) 
    } 
} 

クラスA - 活動のonCreate

Context.startActivity(new Intent(Context,ClassB.class) 
          .putExtra("KEY", new ClassC("TEST")) 
        ); 

ClassC - 活動中に作成

Parcelable parcelable = getIntent().getParcelableExtra("KEY"); 

あなたが最初のテストに合格した場合、次に試してみてください。

Parcel parcel = Parcel.obtain(); 
    parcel.writeParcelable(new ClassC("TEST"),0); 
    Parcelable reRead = parcel.readParcelable(ClassC.class.getClassLoader()); 

をし、私にこの結果を与える:)

do you know what is Parcel ? what is Binder ? 

それが失敗した場合、その後で自分自身を償還するために開始これを読んで:

/** 
* Container for a message (data and object references) that can 
* be sent through an IBinder. A Parcel can contain both flattened data 
* that will be unflattened on the other side of the IPC (using the various 
* methods here for writing specific types, or the general 
* {@link Parcelable} interface), and references to live {@link IBinder} 
* objects that will result in the other side receiving a proxy IBinder 
* connected with the original IBinder in the Parcel. 
* ... 
**/ 
public final class Parcel { 


    ... 

    /** 
    * Read and return a new Parcelable from the parcel. The given class loader 
    * will be used to load any enclosed Parcelables. If it is null, the default 
    * class loader will be used. 
    * @param loader A ClassLoader from which to instantiate the Parcelable 
    * object, or null for the default class loader. 
    * @return Returns the newly created Parcelable, or null if a null 
    * object has been written. 
    * @throws BadParcelableException Throws BadParcelableException if there 
    * was an error trying to instantiate the Parcelable. 
    */ 
    @SuppressWarnings("unchecked") 
    public final <T extends Parcelable> T readParcelable(ClassLoader loader) { 
     Parcelable.Creator<?> creator = readParcelableCreator(loader); 
     if (creator == null) { 
      return null; 
     } 
     if (creator instanceof Parcelable.ClassLoaderCreator<?>) { 
     Parcelable.ClassLoaderCreator<?> classLoaderCreator = 
      (Parcelable.ClassLoaderCreator<?>) creator; 
     return (T) classLoaderCreator.createFromParcel(this, loader); 
     } 
     return (T) creator.createFromParcel(this); 
    } 
    .... 
} 
+0

本当ですか?それはそのままでうまくいくようです。また、[この回答](http://stackoverflow.com/a/31455559/930640)へのコメントでは、誰かが作成者は「インターフェース」のために必要ないと言います。メンバー変数が含まれていない抽象リスナークラスにはまだ必要ですか? – BadCash

+0

@BadCash - – ceph3us

+0

の編集_Why_ Creatorインターフェースを実装する必要がありますか?それはそれなしで完璧に動作するようですか? – BadCash

関連する問題