如何检测RecyclerView是否为空?

时间:2014-12-01 05:20:46

标签: java android android-recyclerview

我有一个RecyclerView从服务器解析外部JSON数据。它工作正常,但JSON上的Volley异步任务有时需要一段时间,当它发生时,片段显示一个空的空白视图。

如何创建测试以检查视图是否为空并显示msg(如果是)?我试着检查一下:

if (recyclerView == null)
if (jsonList == null)
if (adapter.getItemCount() == 0)
if (bundle == null)

但是那些测试要么不做任何事情,要么每次都显示错误信息,即使RecyclerView不是空的。

这是片段上的代码:

public void onViewCreated(View view, Bundle savedInstanceState) {

    LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
    layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
    layoutManager.supportsPredictiveItemAnimations();
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setItemAnimator(new DefaultItemAnimator());
    recyclerView.setClickable(true);
    recyclerView.setHasFixedSize(true);
    recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
    NovaAdapter novaAdapter = new NovaAdapter(getActivity(),jsonList);
    if (novaAdapter.getItemCount() != 0) {
        recyclerView.setAdapter(novaAdapter);
    }else{
        pDialog = new ProgressDialog(getActivity());
        pDialog.setMessage("Retrieving data from Server");
        pDialog.show();            
    }
    super.onViewCreated(view, savedInstanceState);

和适配器上的方法:

@Override
public int getItemCount() {
    return (null != novaList ? novaList.size() : 0);
}

现在,无论视图是否为空,进度对话框始终都会运行。

更新:这是适配器代码:

public class NovaAdapter extends RecyclerView.Adapter<NovaListRowHolder> {

ArrayList<HashMap<String, String>> novaList = new ArrayList<HashMap<String, String>>();
public static final String STATUS = "status";
public static final String NAME = "name";
public static final String ID = "id";
private Context mContext;

public NovaAdapter(Context context, ArrayList<HashMap<String, String>> novaList) {
    this.novaList = novaList;
    this.mContext = context;
}

@Override
public NovaListRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.instances_list, null);
    NovaListRowHolder mh = new NovaListRowHolder(v);
    return mh;
}

@Override
public void onBindViewHolder(NovaListRowHolder novaListRowHolder, int i) {

    HashMap<String, String> e = novaList.get(i);
    novaListRowHolder.name.setText(e.get(NAME));
    novaListRowHolder.status.setText(e.get(STATUS));
    novaListRowHolder.setId(e.get(ID));


}


@Override
public int getItemCount() {
    return (null != novaList ? novaList.size() : 0);
}class NovaListRowHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
protected TextView name;
protected TextView status;
protected String id;

public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}

public NovaListRowHolder(View view) {
    super(view);
    view.setOnClickListener(this);
    this.name = (TextView) view.findViewById(R.id.nameInstance);
    this.status = (TextView) view.findViewById(R.id.statusInstance);

}

public void onClick(View view){
    Dialog dialog = new Dialog(view.getContext());
    dialog.setContentView(R.layout.instances_listdetail);
    dialog.setTitle("Details " + name.getText() + " " + getPosition());
    dialog.show();
}

UPDATE2:

我使用回调接口更新了另一个与上面的类非常相似的类,但是现在recyclerView显示1秒钟然后变为空白。对话框甚至无法显示。这是代码:

public class SubnetsFragment extends Fragment implements OnJSONLoaded{
    /**
     * The fragment argument representing the section number for this
     * fragment.
     */
    private static final String ARG_SECTION_NUMBER = "section_number";
    private OnFragmentInteractionListener mListener;
    public ArrayList<HashMap<String, String>> jsonList;
    public RecyclerView recyclerView;
    public ProgressDialog pDialog;
        /**
     * Returns a new instance of this fragment for the given section
     * number.
     */
    public static SubnetsFragment newInstance(int sectionNumber) {
        SubnetsFragment fragment = new SubnetsFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_SECTION_NUMBER, sectionNumber);
        fragment.setArguments(args);
        return fragment;
    }


    public SubnetsFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        Bundle extras = getArguments();
        Serializable parsedList = extras.getSerializable("SubnetsParsed");
        jsonList = (ArrayList<HashMap<String, String>>)parsedList;
        if (extras == null){
            AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
            alert.setTitle("Token Expired");
            alert.setMessage("Authentication Token expired! Please login again.")
                    .setNeutralButton("Connect", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {
                            Intent intent = new Intent(getActivity(), Login.class);
                            startActivity(intent);
                            getActivity().finish();
                            getFragmentManager().beginTransaction().remove(SubnetsFragment.this).commit();
                        }
                    });
            AlertDialog alertDialog = alert.create();
            alertDialog.show();
        }
        View rootView = inflater.inflate(R.layout.fragment_subnets, container, false);
        recyclerView = (RecyclerView)rootView.findViewById(R.id.subnetsRV);
        return rootView;
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        layoutManager.supportsPredictiveItemAnimations();
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setClickable(true);
        recyclerView.setHasFixedSize(true);
        recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));

        onJsonLoaded(jsonList);

    }

    @Override
    public void onJsonLoaded(ArrayList<HashMap<String, String>> list) {

        SubnetsParser.setOnJSONLoadedListener(new OnJSONLoaded() {
            @Override
            public void onJsonLoaded(ArrayList<HashMap<String, String>> list) {
                if (list.size() != 0){
                    SubnetsAdapter subnetsAdapter = new SubnetsAdapter(getActivity(),jsonList);
                    recyclerView.setAdapter(subnetsAdapter);
                }else {
                    pDialog = new ProgressDialog(getActivity());
                    pDialog.setMessage("Retrieving data from Server");
                    pDialog.show();
                }
            }
        });

    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        ((Stackerz) activity).onSectionAttached(
                getArguments().getInt(ARG_SECTION_NUMBER));
        //try {
        //    mListener = (OnFragmentInteractionListener) activity;
        //} catch (ClassCastException e) {
        //    throw new ClassCastException(activity.toString()
        //            + " must implement OnFragmentInteractionListener");
        //}
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }




    /**
     * This interface must be implemented by activities that contain this
     * fragment to allow an interaction in this fragment to be communicated
     * to the activity and potentially other fragments contained in that
     * activity.
     * <p>
     * See the Android Training lesson <a href=
     * "http://developer.android.com/training/basics/fragments/communicating.html"
     * >Communicating with Other Fragments</a> for more information.
     */
    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        public void onFragmentInteraction(Uri uri);
    }
}

这是JSON Parser类:

public class SubnetsParser extends Activity{
    public static final String NAME = "name";
    public static final String GW = "gw";
    public static final String CIDR = "cidr";
    public static final String ID = "id";

    public String authToken;
    public String neutronURL;

    public static SubnetsParser parser = null;

    public static OnJSONLoaded mListener;

    public static void setOnJSONLoadedListener(OnJSONLoaded listener) {
        mListener = listener;
    }

    public interface OnJSONLoaded {
        void onJsonLoaded(ArrayList<HashMap<String, String>> list);
    }

    public static SubnetsParser shared(){
        if (parser  == null){
            parser  = new SubnetsParser();
        }
        return parser ;
    }

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





    public static ArrayList<HashMap<String, String>> parseJSON(String subnetsJSON){
        ArrayList<HashMap<String, String>> jsonList = new ArrayList<HashMap<String, String>>();
        try {
            Subnets subnets = new Subnets();
            JSONObject subnet = new JSONObject(subnetsJSON);
            JSONArray subnetobj = subnet.getJSONArray("subnets");
            for (int i = 0; i < subnetobj.length(); i++) {
                JSONObject objsrv = subnetobj.getJSONObject(i);
                subnets.setName(objsrv.getString("name"));
                subnets.setGw(objsrv.getString("gateway_ip"));
                subnets.setCidr(objsrv.getString("cidr"));
                subnets.setId(objsrv.getString("id"));
                HashMap<String, String> map = new HashMap<String, String>();
                map.put(NAME, subnets.getName());
                map.put(GW, subnets.getGw());
                map.put(CIDR, subnets.getCidr());
                map.put(ID, subnets.getId());
                jsonList.add(map);
            }
        } catch (JSONException e) {
            Log.d("ErrorInitJSON", e.toString());
            e.printStackTrace();
        }

        Collections.sort(jsonList, new Comparator<HashMap<String, String>>() {
            @Override
            public int compare(HashMap<String, String> lhs, HashMap<String, String> rhs) {
                return (lhs.get("name")).compareToIgnoreCase(rhs.get("name"));
            }
        });

        if (mListener != null) {
            mListener.onJsonLoaded(jsonList);
        }

        return jsonList;

    }


}

5 个答案:

答案 0 :(得分:11)

您可以通过运行来检查它是否为空:

if (adapter.getItemCount() == 0)

如果它不起作用,则表示您没有覆盖适配器上的getItemCount!所以要确保它被覆盖:

@Override
public int getItemCount() {
    return mDataSet.size(); // Where mDataSet is the list of your items
}

更新: 因此,根据您的更新,您可以继续操作。在我看来,你只需要一个回调。您正在检查onViewCreated上的列表是否为空。相反,您应该使用回调。做那样的事情:

public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
    layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
    layoutManager.supportsPredictiveItemAnimations();
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setItemAnimator(new DefaultItemAnimator());
    recyclerView.setClickable(true);
    recyclerView.setHasFixedSize(true);
    recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));

    pDialog = new ProgressDialog(getActivity());
    pDialog.setMessage("Retrieving data from Server");
    pDialog.show();   
}

在你用来填充你的jsonList的类中,我假设一个asynctask或一个单独的类添加这个:

private OnJsonLoaded mListener;

public void setOnJsonLoadedListener(OnJsonLoaded listener) {
    mListener = listener;
}

public interface OnJsonLoaded {
    void onJsonLoaded(ArrayList<HashMap<String, String>> list);
}

现在,在填充ur jsonLise的asynctask中或当json解析器完成其工作时,调用监听器:

if (mListener != null) {
    mListener.onJsonLoaded(jsonList);
}

在您的片段(NovaAdapter novaAdapter = new NovaAdapter(getActivity(),jsonList);以及您的recyclerview)中添加接口实现:

classThatParseJson.setOnJsonLoadedListener(new OnJsonLoaded() {
        @Override
        public void onJsonLoaded(ArrayList<HashMap<String, String>> list) {
            if (list.size() != 0) {
                NovaAdapter novaAdapter = new NovaAdapter(getActivity(),jsonList); 
                recyclerView.setAdapter(novaAdapter);
            } else {
                // Show something like a dialog that the json list is 0 or do whatever you want... here the jsonlist have a count of 0 so it's empty!
            }  
        }
});

代码可能包含错误,我是在不使用IDE的情况下手工编写的,所以也许你必须修复小东西,但逻辑很清楚!

根据您的更新2进行更新:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_subnets, container, false);
    recyclerView = (RecyclerView)rootView.findViewById(R.id.subnetsRV);
    return rootView;
}

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
    layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
    layoutManager.supportsPredictiveItemAnimations();
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setItemAnimator(new DefaultItemAnimator());
    recyclerView.setClickable(true);
    recyclerView.setHasFixedSize(true);
    recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));

    // start json parser here instead of passing to fragment as a bundle
    SubnetsParser.parseJSON(yourparams);
}

@Override
public void onJsonLoaded(ArrayList<HashMap<String, String>> list) {

    SubnetsParser.setOnJSONLoadedListener(new OnJSONLoaded() {
        @Override
        public void onJsonLoaded(ArrayList<HashMap<String, String>> list) {
            if (list.size() != 0){
                SubnetsAdapter subnetsAdapter = new SubnetsAdapter(getActivity(),jsonList);
                recyclerView.setAdapter(subnetsAdapter);
            }else {
                //pDialog = new ProgressDialog(getActivity());
                //pDialog.setMessage("Retrieving data from Server");
                //pDialog.show();
                //Instead of a progressdialog, put here a dialog informing that the list is empty!
            }
        }
    });

}

答案 1 :(得分:3)

如何在https://developer.android.com/training/material/lists-cards.html

中描述

布局管理器调用overriden方法getItemCount()。 这是片段:

// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
    return mDataset.length;
}

因此,要检测recyclerView是否为空,您必须向LayoutManager申请。例如:

if( mLayoutManager.getItemCount() == 0 ){
    //Do something
}

我尝试getItemCount() Adapter,但这会返回0,我不知道原因是什么......

答案 2 :(得分:0)

如果(adapter.getItemCount()== 0)

这样做对我有用...

答案 3 :(得分:0)

您可以使用接口回调来实现:

  1. 创建界面
public interface OnAdapterCountListener {
    void onAdapterCountListener(int count);
}
  1. 在适配器中添加以下变量和方法
private OnAdapterCountListener onAdapterCountListener; 
    public void setOnAdapterCountListener(OnAdapterCountListener l) { 
        onAdapterCountListener = l; 
    }
  1. 将此行添加到适配器的onCreateViewHolder中
onAdapterCountListener.onAdapterCountListener(getItemCount());
  1. 最后,在您的活动中调用界面
listAdapter.setOnAdapterCountListener(new OnAdapterCountListener() {
    @Override 
    public void onAdapterCountListener(int count) { 
        if (count > 0) 
            adapterEmptyText.setVisibility(View.GONE); 
    }
});

答案 4 :(得分:0)

创建一个类并继承 Recyclerview - 按照下面的代码

public class RecyclerviewEmpty extends RecyclerView {

private View emptyView;

private final AdapterDataObserver observer = new AdapterDataObserver() {
    @Override
    public void onChanged() {
        checkIfEmpty();
    }

    @Override
    public void onItemRangeInserted(int positionStart, int itemCount) {
        checkIfEmpty();
    }

    @Override
    public void onItemRangeRemoved(int positionStart, int itemCount) {
        checkIfEmpty();
    }
};

public RecyclerviewEmpty(@NonNull Context context) {
    super(context);
}

public RecyclerviewEmpty(@NonNull Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
}

public RecyclerviewEmpty(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}


private void checkIfEmpty() {
    if (emptyView != null && getAdapter() != null) {
        final boolean emptyViewVisible = getAdapter().getItemCount() == 0;
        emptyView.setVisibility(emptyViewVisible ? VISIBLE : GONE);
        setVisibility(emptyViewVisible ? GONE : VISIBLE);
    }
}

@Override
public void setAdapter(@Nullable Adapter adapter) {
    final Adapter oldAdapter = getAdapter();
    if (oldAdapter != null) {
        oldAdapter.unregisterAdapterDataObserver(observer);
    }
    super.setAdapter(adapter);
    if (adapter != null) {
        adapter.registerAdapterDataObserver(observer);
    }

    checkIfEmpty();
}

public void setEmptyView(View emptyView) {
    this.emptyView = emptyView;
    checkIfEmpty();
}

activity_xml - 在视图中定义类名

    <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/bg_main"
    tools:context=".Ui.FavouriteActivity">


    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <view
            android:id="@+id/rv_fav_activity"
            class="com.kumar.random.quotes.Views.RecyclerviewEmpty"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <TextView
            android:id="@+id/list_empty1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:gravity="center"
            android:text="Empty Favourite"
            android:textSize="14sp" />
    </FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

Activity.java

    private RecyclerviewEmpty rvFavourite;
private void setUpRv() {
        rvFavourite.setEmptyView(emptyView);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        MainQuotesAdapter adapter = new MainQuotesAdapter(this, favouriteItem);
        rvFavourite.setLayoutManager(layoutManager);
        rvFavourite.setAdapter(adapter);
    }

请注意_01:

 rvFavourite.setEmptyView(emptyView);

请注意_02:

public void setEmptyView(View emptyView) {
    this.emptyView = emptyView;
    checkIfEmpty();
}

请注意_03

 <view
        android:id="@+id/rv_fav_activity"
        class="com.kumar.random.quotes.Views.RecyclerviewEmpty"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />