2014-12-01 33 views
7

Bir sunucudan ayrıştırılan harici JSON verilerini alma konusunda bir RecyclerView var. İyi çalışır, ancak JSON'daki Volley zaman uyumsuzluğu görevi bir süre alır ve parçanın boş bir boş görüntüyü görüntülediği zaman.RecyclerView boş ise nasıl algılanır?

Görünümün boş olup olmadığını ve olup olmadığını kontrol etmek için nasıl bir test oluşturabilirim?

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

Ama bu testler ya hiçbir şey yoktur ya da hata mesaj RecyclerView boş olmasa bile her seferinde görüntüler: Ben kontrol etmeye çalıştı.

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

ve Adaptör üzerindeki yöntemi::

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

görünümü boşsa hep iletişim ilerleme olursa olsun çalıştırmak Şimdiki durumda

Bu

parçacık üzerinde koddur ya da değil.

GÜNCELLEME:

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:

Hemen hemen şimdi ancak bir geri arama arayüzüne 1 saniye boyunca recyclerView görüntüler ile yukarıdaki ile aynı olan başka bir sınıf güncellenen İşte adaptör kod ve sonra boş gider. Diyalog bile göstermiyor. İşte kod:

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

Ve bu JSON Ayrıştırıcı sınıftır:

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

Neden bir progressbar görünmüyor ?? Bu asynctask ile çok yaygın bir kullanım. – Mike

+0

İlerleme çubuğunu Volley ile nasıl kullanabilirim? Benim app yapılandırılmış voleybolu bir geri dönüşüm sınıfı – GITcommitEd

+0

RecyclerView aslında bir "ViewGroup" parçası tarafından denilen bir arka plan sınıfında kullanılır, hiç denediniz mi "RecyclerView.getChildCount() == 0"? – VinceStyling

cevap

7

Sen çalıştırarak içi boş olduğunda kontrol edebilirsiniz:

if (adapter.getItemCount() == 0) 

onu çalışmıyor ise size sığınak demektir Adaptörünüzde getItemCount'ı geçersiz kılmayın! böylece overrided emin olun:

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

Güncelleme: Yani bu Devam nasıl olduğunu Güncellemenize dayalı. Benim görüşüme göre sadece bir geri aramaya ihtiyacınız var. Listenin onViewCreated'ınızda boş olup olmadığını kontrol ediyorsunuz. Bunun yerine, bir geri arama kullanmalısınız. Böyle bir şey yapın: Eğer jsonList doldurmak için kullandığınız sınıfta

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

, ben bir asynctask veya ayrı sınıf bu eklemek varsayalım:

private OnJsonLoaded mListener; 

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

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

şimdi, ur jsonLise doldurmak asynctask içinde senin recyclervi ve; senin fragmanı (novaAdapter novaAdapter = new novaAdapter (getActivity(), jsonList) ile birinde

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

: ya json ayrıştırıcı işini bitirdiğinde, dinleyici çağrı ew) arayüz uygulamasını ekleyin:

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

kod containts hataları, ben elleriyle yazdığını böylece belki küçük şeyleri düzeltmek zorunda ama mantık oldukça açıktır IDE kullanmadan!senin Güncelleme 2 dayanan

Güncelleme:

@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

Bunu denedim ama şunu elde ettim: java.lang.NullPointerException: app.Instances.NovaAdapter.getItemCount – GITcommitEd

+0

adresindeki boş nesne başvurusu için sanal yöntem 'int java.util.ArrayList.size()' öğesini çağırmayı deneyin. yöntem şu şekildedir: @Override public int getItemCount() { return (null! = novaList? novaList.size(): 0); } – GITcommitEd

+0

öyleyse, @Override public int getItemCount() {return (null! = NovaList? NovaList.size(): 0); Viewholdercreated parçası hariç tüm kaynak bağdaştırıcınızı göster bana – iGio90

3

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

overriden yöntem getItemCount() düzen yöneticisi tarafından çağrılır açıklanan nasıl. Bu snippet'tir: recyclerView Eğer LayoutManager bunu talep etmelidir boşsa

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

Yani algılamak için. Örnek:

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

benim Adapter ait getItemCount() çalışıyorum ama neden bu 0 döndürür, bilmiyorum ...