如何在Android中使用Firebase实现自定义PagerAdapter?

时间:2017-07-07 04:17:56

标签: android firebase firebase-realtime-database android-viewpager android-pageradapter

我正在尝试以与FirebaseListAdapter和FirebaseRecyclerAdapter相同的方式实现实现Firebase的自定义PagerAdapter。我查看了GitHub here上的源代码,但我在Android Studio中遇到了一些错误。这是我的FirebasePagerAdapter,它使用了给定链接中的许多类:

    public abstract class FirebasePagerAdapter<T> extends PagerAdapter implements FirebaseAdapter, ChangeEventListener {

    private static String TAG = "firebasepageradapter";
    protected final Activity mActivity;
    protected final ObservableSnapshotArray<T> mSnapshots;
    protected final int mLayout;

    /**
     * @param activity    The {@link Activity} containing the {@link android.support.v4.view.ViewPager}
     * @param modelLayout This is the layout used to represent a single list item. You will be
     *                    responsible for populating an instance of the corresponding view with the
     *                    data from an instance of modelClass.
     * @param snapshots   The data used to populate the adapter
     */
    public FirebasePagerAdapter(Activity activity,
                               ObservableSnapshotArray<T> snapshots,
                               @LayoutRes int modelLayout) {
        mActivity = activity;
        mSnapshots = snapshots;
        mLayout = modelLayout;

        startListening();
    }

    /**
     * @param parser a custom {@link SnapshotParser} to convert a {@link DataSnapshot} to the model
     *               class
     * @param query  The Firebase location to watch for data changes. Can also be a slice of a
     *               location, using some combination of {@code limit()}, {@code startAt()}, and
     *               {@code endAt()}. <b>Note, this can also be a {@link DatabaseReference}.</b>
     * @see #FirebasePagerAdapter(Activity, ObservableSnapshotArray, int)
     */
    public FirebasePagerAdapter(Activity activity,
                               SnapshotParser<T> parser,
                               @LayoutRes int modelLayout,
                               Query query) {
        this(activity, new FirebaseArray<>(query, parser), modelLayout);
    }

    /**
     * @see #FirebasePagerAdapter(Activity, SnapshotParser, int, Query)
     */
    public FirebasePagerAdapter(Activity activity,
                               Class<T> modelClass,
                               @LayoutRes int modelLayout,
                               Query query) {
        this(activity, new ClassSnapshotParser<>(modelClass), modelLayout, query);
    }

    @Override
    public int getCount() {
        return mSnapshots.size();
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return false;
    }

    @Override
    public void startListening() {
        if (!mSnapshots.isListening(this)) {
            mSnapshots.addChangeEventListener(this);
        }
    }

    @Override
    public void cleanup() {
        mSnapshots.removeChangeEventListener(this);
    }

    @Override
    public Object getItem(int position) {
        return mSnapshots.get(position).getKey().hashCode();
    }

    @Override
    public DatabaseReference getRef(int position) {
        return mSnapshots.get(position).getRef();
    }

    @Override
    public void onChildChanged(ChangeEventListener.EventType type, DataSnapshot snapshot, int index, int oldIndex) {
        notifyDataSetChanged();
    }

    @Override
    public void onDataChanged() {

    }

    @Override
    public void onCancelled(DatabaseError error) {
        Log.w(TAG, error.toException());
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        View view = mActivity.getLayoutInflater().inflate(mLayout, container, false);

        T model = getItem(position);

        // Call out to subclass to marshall this model into the provided view
        populateView(view, model, position);

        return view;
    }

    /**
     * Each time the data at the given Firebase location changes,
     * this method will be called for each item that needs to be displayed.
     * The first two arguments correspond to the mLayout and mModelClass given to the constructor of
     * this class. The third argument is the item's position in the list.
     * <p>
     * Your implementation should populate the view using the data contained in the model.
     *
     * @param v        The view to populate
     * @param model    The object containing the data used to populate the view
     * @param position The position in the list of the view being populated
     */
    protected abstract void populateView(View v, T model, int position);

}

从给定链接使用的类:

  • ChangeEventListener
  • ClassSnapshotParser
  • FirebaseAdapter
  • FirebaseArray
  • ObservableSnapshotArray
  • 前提条件
  • SnapshotParser

我在Google和SO上搜索了一个示例或解决方案,但是尽管需要FirebasePagerAdapter,没有人提出解决方案或至少公开它。我想让这个工作,并让其他可能觉得有用的开发人员公开。

我得到的错误是在instantiateItem方法中使用T model = getItem(position);&#34;不兼容的类型:必需的T,找到的对象&#34; 并且使用this(activity, new FirebaseArray<>(query, parser), modelLayout);&#34;无法推断参数&#34;。

我希望通过解决这些错误,适配器可以按预期工作。

1 个答案:

答案 0 :(得分:0)

我已经通过将getItem方法更改为GenericType public T getItem(int position)来解决了这个问题。它现在完美运作。这是我完整的FirebasePagerAdapter类:

    public abstract class FirebasePagerAdapter<T> extends PagerAdapter implements FirebaseAdapter, ChangeEventListener {

    private static String TAG = "firebasepageradapter";
    protected final Activity mActivity;
    protected final ObservableSnapshotArray<T> mSnapshots;
    protected final int mLayout;

    /**
     * @param activity    The {@link Activity} containing the {@link android.support.v4.view.ViewPager}
     * @param modelLayout This is the layout used to represent a single list item. You will be
     *                    responsible for populating an instance of the corresponding view with the
     *                    data from an instance of modelClass.
     * @param snapshots   The data used to populate the adapter
     */
    public FirebasePagerAdapter(Activity activity,
                               ObservableSnapshotArray<T> snapshots,
                               @LayoutRes int modelLayout) {
        mActivity = activity;
        mSnapshots = snapshots;
        mLayout = modelLayout;

        startListening();
    }

    /**
     * @param parser a custom {@link SnapshotParser} to convert a {@link DataSnapshot} to the model
     *               class
     * @param query  The Firebase location to watch for data changes. Can also be a slice of a
     *               location, using some combination of {@code limit()}, {@code startAt()}, and
     *               {@code endAt()}. <b>Note, this can also be a {@link DatabaseReference}.</b>
     * @see #FirebasePagerAdapter(Activity, ObservableSnapshotArray, int)
     */
    public FirebasePagerAdapter(Activity activity,
                               SnapshotParser<T> parser,
                               @LayoutRes int modelLayout,
                               Query query) {
        this(activity, new FirebaseArray<>(query, parser), modelLayout);
    }

    /**
     * @see #FirebasePagerAdapter(Activity, SnapshotParser, int, Query)
     */
    public FirebasePagerAdapter(Activity activity,
                               Class<T> modelClass,
                               @LayoutRes int modelLayout,
                               Query query) {
        this(activity, new ClassSnapshotParser<>(modelClass), modelLayout, query);
    }

    @Override
    public int getCount() {
        return mSnapshots.size();
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    @Override
    public void startListening() {
        if (!mSnapshots.isListening(this)) {
            mSnapshots.addChangeEventListener(this);
        }
    }

    @Override
    public void cleanup() {
        mSnapshots.removeChangeEventListener(this);
    }

    @Override
    public T getItem(int position) {
        return mSnapshots.getObject(position);
    }

    @Override
    public DatabaseReference getRef(int position) {
        return mSnapshots.get(position).getRef();
    }

    @Override
    public void onChildChanged(ChangeEventListener.EventType type, DataSnapshot snapshot, int index, int oldIndex) {
        notifyDataSetChanged();
    }

    @Override
    public void onDataChanged() {

    }

    @Override
    public void onCancelled(DatabaseError error) {
        Log.w(TAG, error.toException());
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        View view = mActivity.getLayoutInflater().inflate(mLayout, container, false);

        //T model = getItem(position);
        T model = getItem(position);

        // Call out to subclass to marshall this model into the provided view
        populateView(view, model, position);
        container.addView(view);
        return view;
    }

    /**
     * Each time the data at the given Firebase location changes,
     * this method will be called for each item that needs to be displayed.
     * The first two arguments correspond to the mLayout and mModelClass given to the constructor of
     * this class. The third argument is the item's position in the list.
     * <p>
     * Your implementation should populate the view using the data contained in the model.
     *
     * @param v        The view to populate
     * @param model    The object containing the data used to populate the view
     * @param position The position in the list of the view being populated
     */
    protected abstract void populateView(View v, T model, int position);

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((RelativeLayout)object);
    }

}

我已经发布了为GitHub工作所需的所有内容,以供其他可能认为有用的人使用。你可以找到它here