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

How to implement custom PagerAdapter using Firebase in Android?

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

中的大量 类
    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);

}

类 使用给定 link:

我在 Google 和 SO 中搜索了示例或解决方案,但尽管需要 FirebasePagerAdapter,但没有人提出解决方案或至少没有人提出解决方案 public。我想让它工作并使它 public 供其他可能发现它有用的开发人员使用。

我遇到的错误是在 instantiateItem 方法 T model = getItem(position); 中 "incompatible types: required T, found object" 和 this(activity, new FirebaseArray<>(query, parser), modelLayout); "cannot infer arguments".

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

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

    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