如何检测RecyclerView是否为空? [英] How to detect if RecyclerView is empty?
问题描述
我有一个RecyclerView,它从服务器获取外部JSON数据.它可以正常工作,但是基于JSON的Volley异步任务有时会花费一些时间,当它执行时,片段将显示一个空的空白视图.
I have a RecyclerView getting external JSON data parsed from a server. It works fine however the Volley async task on JSON sometimes takes a while and when it does the fragment displays an empty blank view.
如何创建测试以查看视图是否为空并显示消息(如果显示)?我试图检查:
How can I create a test to check if the view is empty and display a msg if it is? I tried to check:
if (recyclerView == null)
if (jsonList == null)
if (adapter.getItemCount() == 0)
if (bundle == null)
但是这些测试不执行任何操作,或者即使RecyclerView不为空,它们也每次都会显示错误消息.
But those tests either dont do anything or they display the error message every single time even if the RecyclerView is not empty.
这是片段上的代码:
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);
}
无论视图是否为空,现在总是以进度对话框的方式运行.
The way it is now the progress dialog always run no matter if the view is empty or not.
更新:这是适配器代码:
UPDATE: Here's the adapter code:
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秒钟,然后变为空白.该对话框甚至没有显示.这是代码:
I updated another class which is pretty much the same as the one above with a callback interface however now the recyclerView displays for 1 second and then goes blank. The dialog doesn't even show. Here's the code:
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类:
And this is the JSON Parser class:
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;
}
}
推荐答案
您可以通过运行以下命令检查其是否为空:
You can check if it's empty by running:
if (adapter.getItemCount() == 0)
如果它不起作用,则意味着您尚未覆盖适配器上的getItemCount!因此请确保已将其覆盖:
If it's not working it means you haven't Override the getItemCount on your adapter! so make sure it's overrided:
@Override
public int getItemCount() {
return mDataSet.size(); // Where mDataSet is the list of your items
}
更新: 因此,根据您的更新,这就是您可以继续进行的方式.我认为您只需要回调即可.您正在检查onViewCreated上的列表是否为空.您应该改为使用回调.做这样的事情:
Update: So based on your update this is how you could proceed. In my opinion you just need a callback. You are checking if the list is empty on your onViewCreated. You should, instead, use a callback. Do something like that:
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或一个单独的类将其添加:
In the class you are using to populate your jsonList, I assume an asynctask or a separate class add this:
private OnJsonLoaded mListener;
public void setOnJsonLoadedListener(OnJsonLoaded listener) {
mListener = listener;
}
public interface OnJsonLoaded {
void onJsonLoaded(ArrayList<HashMap<String, String>> list);
}
现在,在填充您的jsonLise的asynctask或json解析器完成工作时,调用侦听器:
now, in the asynctask that populate ur jsonLise or when the json parser finish his job, call the listener:
if (mListener != null) {
mListener.onJsonLoaded(jsonList);
}
在您的片段(带有NovaAdapter novaAdapter = new NovaAdapter(getActivity(),jsonList);和您的recyclerview的片段)中,添加接口实现:
In your fragment (the one with NovaAdapter novaAdapter = new NovaAdapter(getActivity(),jsonList); and your recyclerview) add the interface implementation:
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的情况下手动编写了代码,因此也许您必须修复一些小问题,但逻辑很明确!
the code may containts errors, i written it by hand without using IDE so maybe you have to fix small things but the logic is quite clear!
根据您的更新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!
}
}
});
}
这篇关于如何检测RecyclerView是否为空?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!