加载数据后,RecyclerView仍为空白

时间:2018-03-08 00:44:10

标签: android android-recyclerview android-cardview swiperefreshlayout

我在RecyclerView内处理SwipeRefreshLayout,其中包含CardViews基于从API调用中检索到的数据。这在一个应用中的Fragment中实现,而在另一个应用中直接在Activity中实现。

虽然此代码(经适当修改)在Activity中正常工作,但片段中的变体始终显示为空白 - 即使我已验证已收到数据。即使播种假人CardView也不会显示任何内容。

我做错了什么或错过了什么?

OnCreateView中的初始化如下:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate (R.layout.fragment_revive_housecall, container, false);
    ...
    ...
    constraintLayout = view.findViewById (R.id.constraintLayout);
    swipeRefreshLayout = (SwipeRefreshLayout) view.findViewById (R.id.swipeRefreshLayout);
    recyclerView = (RecyclerView) view.findViewById (R.id.recyclerView);
    emptyView = (TextView) view.findViewById (R.id.empty_view);
    houseCallList = new ArrayList<> ();
    adapter = new HouseCallAdapter (getActivity ().getApplicationContext (), houseCallList);
    if(houseCallList.isEmpty ()) {
        emptyView.setText (R.string.pulltorefresh);
        recyclerView.setVisibility (View.GONE);
        emptyView.setVisibility (View.VISIBLE);
    } else {
        //emptyView.setVisibility (View.GONE);
        recyclerView.setVisibility (View.VISIBLE);
        adapter.notifyDataSetChanged();
    }
    recyclerView.setLayoutManager (new LinearLayoutManager (getActivity ().getApplicationContext ()));
    recyclerView.setItemAnimator (new DefaultItemAnimator ());
    recyclerView.setAdapter (adapter);
    adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {

        @Override
        public void onChanged() {
            super.onChanged();
            checkEmpty();
        }

        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            super.onItemRangeInserted(positionStart, itemCount);
            checkEmpty();
        }

        @Override
        public void onItemRangeRemoved(int positionStart, int itemCount) {
            super.onItemRangeRemoved(positionStart, itemCount);
            checkEmpty();
        }

        void checkEmpty() {
            emptyView.setText (R.string.no_data_available);
            emptyView.setVisibility(adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
            recyclerView.setVisibility (adapter.getItemCount() == 0 ? View.GONE : View.VISIBLE);
        }
    });
    ItemTouchHelper.SimpleCallback itemTouchHelperCallback = new RecyclerItemTouchHelper(0, ItemTouchHelper.LEFT /*| ItemTouchHelper.RIGHT*/, this);
    new ItemTouchHelper(itemTouchHelperCallback).attachToRecyclerView(recyclerView);
    swipeRefreshLayout.setOnRefreshListener (new SwipeRefreshLayout.OnRefreshListener () {
        @Override
        public void onRefresh() {
            loadHouseCallRequests(null);  // in this function call onItemsLoadComplete when done
        }
    });
    return view;
}

OnSwiped覆盖如下:

@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction, int position) {
    if (viewHolder instanceof HouseCallAdapter.MyViewHolder) {
        // get the removed item name to display it in snack bar
        String housecallid = houseCallList.get(viewHolder.getAdapterPosition()).getHousecallid ();

        // backup of removed item for undo purpose
        final HouseCall deletedItem = houseCallList.get(viewHolder.getAdapterPosition());
        final int deletedIndex = viewHolder.getAdapterPosition();

        // remove the item from recycler view
        adapter.removeItem(viewHolder.getAdapterPosition());
        if (direction == ItemTouchHelper.LEFT) {
            ((HouseCallAdapter.MyViewHolder) viewHolder).viewBackground.setBackgroundColor (getResources ().getColor (R.color.bg_row_background_decline));
            // showing snack bar with Undo option
            Snackbar snackbar = Snackbar
                    .make(constraintLayout, "Request " + housecallid + " declined!", Snackbar.LENGTH_LONG);
            snackbar.setAction("UNDO", new View.OnClickListener() {
                @Override
                public void onClick(View view) {

                    // undo is selected, restore the deleted item
                    adapter.restoreItem(deletedItem, deletedIndex);
                }
            });
            snackbar.setActionTextColor(Color.RED);
            snackbar.show();
        }
    }
}

void onItemsLoadComplete() {
    swipeRefreshLayout.setRefreshing(false);
}

private void loadHouseCallRequests(@Nullable JsonObject params) {
    // This is the code that generates the dummy cardview
    /*HouseCall call = new HouseCall ("abc123", "open", "12/02/1991", "26/02/2018:22:39", "general", "6", "XY", "AB", "ACB@XZY.com", "Male", "Line1", "Line2", "Line3", "City", "State", "123456789");
    houseCallList.add (call);*/

    adapter.notifyDataSetChanged();
    onItemsLoadComplete ();
    if (params == null) {
        params = new JsonObject ();
        params.addProperty ("email", email);
    }
    GetHouseCalls calls = new GetHouseCalls ();
    calls.execute (params);
}

适配器

public class HouseCallAdapter extends RecyclerView.Adapter<HouseCallAdapter.MyViewHolder> {

private Context mContext;
private List<HouseCall> houseCallList;

private static final int DATASET_EMPTY = 0;
private static final int DATA_AVAILABLE = 1;


public class MyViewHolder extends RecyclerView.ViewHolder{

    public TextView txtFname, txtLname, txtDob, txtSex, txtAddress, txtMobile;
    public ConstraintLayout viewBackground, viewForeground;


    public MyViewHolder(View itemView) {
        super (itemView);
        txtName = itemView.findViewById (R.id.txtName);
        ... // add data to the layout of the 
    }

}

public HouseCallAdapter(Context mContext, List<HouseCall> houseCallList) {
    this.mContext = mContext;
    this.houseCallList = houseCallList;
}


@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View itemView = LayoutInflater.from (parent.getContext ())
            .inflate (R.layout.housecall_request, parent, false);
    return new MyViewHolder (itemView);
}

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
    HouseCall houseCall = houseCallList.get (position);
    ... // retreive data from UI elements and set data in UI
}


@Override
public int getItemCount() {
    return houseCallList.size ();
}

public void removeItem(int position) {
    houseCallList.remove(position);
    // notify the item removed by position
    // to perform recycler view delete animations
    // NOTE: don't call notifyDataSetChanged()
    notifyItemRemoved(position);
}

public void restoreItem(HouseCall item, int position) {
    houseCallList.add(position, item);
    // notify item added by position
    notifyItemInserted(position);
}
}

Recycler Item Touch Helper

public class RecyclerItemTouchHelper extends ItemTouchHelper.SimpleCallback {
private RecyclerItemTouchHelperListener listener;

public RecyclerItemTouchHelper(int dragDirs, int swipeDirs, RecyclerItemTouchHelperListener listener) {
    super(dragDirs, swipeDirs);
    this.listener = listener;
}

@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
    return true;
}

@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
    if (viewHolder != null) {
        final View foregroundView = ((HouseCallAdapter.MyViewHolder) viewHolder).viewForeground;

        getDefaultUIUtil().onSelected(foregroundView);
    }
}

@Override
public void onChildDrawOver(Canvas c, RecyclerView recyclerView,
                            RecyclerView.ViewHolder viewHolder, float dX, float dY,
                            int actionState, boolean isCurrentlyActive) {
    final View foregroundView = ((HouseCallAdapter.MyViewHolder) viewHolder).viewForeground;
    getDefaultUIUtil().onDrawOver(c, recyclerView, foregroundView, dX, dY,
            actionState, isCurrentlyActive);
}

@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    final View foregroundView = ((HouseCallAdapter.MyViewHolder) viewHolder).viewForeground;
    getDefaultUIUtil().clearView(foregroundView);
}

@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView,
                        RecyclerView.ViewHolder viewHolder, float dX, float dY,
                        int actionState, boolean isCurrentlyActive) {
    final View foregroundView = ((HouseCallAdapter.MyViewHolder) viewHolder).viewForeground;

    getDefaultUIUtil().onDraw(c, recyclerView, foregroundView, dX, dY,
            actionState, isCurrentlyActive);
}

@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
    listener.onSwiped(viewHolder, direction, viewHolder.getAdapterPosition());
}

@Override
public int convertToAbsoluteDirection(int flags, int layoutDirection) {
    return super.convertToAbsoluteDirection(flags, layoutDirection);
}

public interface RecyclerItemTouchHelperListener {
    void onSwiped(RecyclerView.ViewHolder viewHolder, int direction, int position);
}
}

布局xml

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.testapp.appname.FragmentCards">

<android.support.v4.widget.SwipeRefreshLayout
    android:id="@+id/swipeRefreshLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/empty_view"
        android:layout_width="wrap_content"
        android:layout_height="18dp"
        android:gravity="center_vertical"
        android:text="@string/no_data_available"
        android:textAlignment="center"
        android:visibility="visible"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="0.698"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical"
        android:visibility="visible" />

</android.support.v4.widget.SwipeRefreshLayout>

1 个答案:

答案 0 :(得分:0)

感谢@ MohammedFarhan的建议,我查看了UI的XML布局,并在那里发现了问题。

在较旧的布局中,RecyclerView被隐藏,并且在屏幕上不可见,因此手机上的空白屏幕。

<android.support.constraint.ConstraintLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.testapp.appname.FragmentCards">

<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
    android:id="@+id/empty_view"
    android:layout_width="wrap_content"
    android:layout_height="18dp"
    android:gravity="center_vertical"
    android:text="@string/no_data_available"
    android:textAlignment="center"
    android:visibility="visible"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintHorizontal_bias="0.698"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<android.support.v7.widget.RecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="vertical"
    android:visibility="visible" />

我需要做的就是将RecyclerView顶部的约束添加到父级,并将TextView移动到ConstraintLayout的子级。

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.testapp.appname.FragmentCards">

<TextView
    android:id="@+id/empty_view"
    android:layout_width="0dp"
    android:layout_height="92dp"
    android:gravity="center_vertical"
    android:text="@string/no_data_available"
    android:textAlignment="center"
    android:visibility="visible"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="0.498" />

<android.support.v4.widget.SwipeRefreshLayout
    android:id="@+id/swipeRefreshLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="0dp"
        android:scrollbars="vertical"
        android:visibility="visible"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:layout_editor_absoluteX="8dp" />

</android.support.v4.widget.SwipeRefreshLayout>

</android.support.constraint.ConstraintLayout>