我有一个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;
}
}
答案 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)
您可以使用接口回调来实现:
public interface OnAdapterCountListener {
void onAdapterCountListener(int count);
}
private OnAdapterCountListener onAdapterCountListener;
public void setOnAdapterCountListener(OnAdapterCountListener l) {
onAdapterCountListener = l;
}
onAdapterCountListener.onAdapterCountListener(getItemCount());
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" />