2014-12-01 32 views
7

Tôi có RecyclerView lấy dữ liệu JSON bên ngoài được phân tích từ máy chủ. Nó hoạt động tốt tuy nhiên nhiệm vụ asen Volley trên JSON đôi khi mất một thời gian và khi nó mảnh vỡ sẽ hiển thị một cái nhìn trống rỗng.Cách phát hiện xem RecyclerView có trống không?

Làm cách nào để tạo thử nghiệm để kiểm tra xem chế độ xem có trống không và hiển thị thông báo nếu nó là? Tôi cố gắng để kiểm tra:

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

Nhưng những xét nghiệm hoặc không làm bất cứ điều gì hoặc họ hiển thị các thông báo lỗi mỗi lần duy nhất ngay cả khi RecyclerView là không có sản phẩm nào.

Đây là mã trên đoạn:

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); 

và phương pháp trên Adaptor:

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

Cách nó bây giờ là tiến thoại luôn chạy không có vấn đề nếu xem là trống rỗng hay không.

UPDATE: Đây là mã adapter:

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:

tôi cập nhật một lớp học mà là khá nhiều giống như một ở trên với một giao diện callback tuy nhiên bây giờ hiển thị recyclerView trong 1 giây và sau đó để trống. Hộp thoại thậm chí không hiển thị. Dưới đây là các mã:

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); 
    } 
} 

Và đây là lớp 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

Tại sao không hiển thị một progressbar ?? Đó là một cách sử dụng rất phổ biến với asynctask. – Mike

+0

Làm cách nào tôi có thể sử dụng thanh tiến trình với Volley? Cách ứng dụng của tôi được định cấu hình volley được sử dụng trong một lớp nền được gọi bởi một đoạn – GITcommitEd

+0

RecyclerView thực sự là một 'ViewGroup', bạn đã bao giờ thử" RecyclerView.getChildCount() == 0 "chưa? – VinceStyling

Trả lời

7

Bạn có thể kiểm tra nếu nó trống bằng cách chạy:

if (adapter.getItemCount() == 0) 

Nếu nó không làm việc nó có nghĩa là bạn thiên đường Ghi đè lên getItemCount trên bộ điều hợp của bạn! do đó hãy chắc chắn rằng nó overrided:

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

Cập nhật: Vì vậy, dựa trên bản cập nhật của bạn đây là cách bạn có thể tiến hành. Theo tôi, bạn chỉ cần gọi lại. Bạn đang kiểm tra xem danh sách có trống trên onViewCreated của bạn không. Thay vào đó, bạn nên sử dụng gọi lại. Làm một cái gì đó như thế:

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(); 
} 

Trong lớp bạn đang sử dụng để cư jsonList của bạn, tôi giả sử một AsyncTask hoặc một lớp riêng biệt thêm này:

private OnJsonLoaded mListener; 

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

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

bây giờ, trong AsyncTask rằng cư ur jsonLise hoặc khi phân tích cú pháp jSON kết thúc công việc của mình, hãy gọi người nghe:

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

Trong đoạn của bạn (một với novaAdapter novaAdapter = novaAdapter mới (getActivity(), jsonList); và recyclervi của bạn ew) thêm việc thực hiện giao diện:

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! 
      } 
     } 
}); 

mã có thể containts lỗi, tôi viết nó bằng tay mà không sử dụng IDE như vậy có lẽ bạn cần phải sửa chữa những điều nhỏ nhặt nhưng logic là khá rõ ràng!

Cập nhật dựa trên Cập nhật của bạn 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! 
      } 
     } 
    }); 

} 
+0

Tôi đã thử nhưng tôi nhận được: java.lang.NullPointerException: Cố gắng gọi phương thức ảo 'int java.util.ArrayList.size()' trên tham chiếu đối tượng null tại app.Instances.NovaAdapter.getItemCount – GITcommitEd

+0

Đây là cách trước đây là: @Override public int getItemCount() { return (null! = novaList? novaList.size(): 0); } – GITcommitEd

+0

vì vậy hãy giữ nguyên nó trước khi @Override public int getItemCount() {return (null! = NovaList? NovaList.size(): 0); chỉ cho tôi bộ điều hợp nguồn đầy đủ của bạn ngoại trừ phần viewholdercreated – iGio90

3

Làm thế nào được mô tả trong https://developer.android.com/training/material/lists-cards.html

Phương pháp overriden getItemCount() được gọi bởi người quản lý bố trí. Đây là đoạn:

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

Vì vậy, để phát hiện nếu recyclerView trống bạn phải yêu cầu nó để LayoutManager của bạn. Ví dụ:

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

tôi cố gắng getItemCount() của Adapter của tôi nhưng điều này trả về 0, tôi không biết tại sao nó là ...

Các vấn đề liên quan