2015-11-09 17 views
5

Sono abbastanza nuovo per Android e sto costruendo e app con un gruppo di amici del college. Il problema che abbiamo incontrato è che quando si riempie l'elenco di elementi da visualizzare recuperando dati da un server, i dati vengono caricati e aggiunti a un elenco ma il recyclerView non lo visualizza mai (anche dopo aver chiamato NotifyDataSetChanged dal mio adattatore personalizzato). Quando abbiamo usato i dati hardcoded per testare l'app, questo non è mai successo.RecyclerView non si aggiorna dopo NotifyDataSetChanged(), il contenuto appare dopo l'accensione e lo spegnimento Schermo

La parte strana è che l'elenco degli elementi viene visualizzato su recyclerView dopo aver spento il display e quindi riacceso (onBindViewHolder del mio adattatore personalizzato viene chiamato quando riaccendo lo schermo). Inoltre, se Sostituisco il frammento che contiene il recyclerView con un altro e quindi ritorno ad esso i dati vengono caricati nella lista ma non mostrati.

Quello che voglio sapere è perché sta accadendo questo e cosa posso fare per risolverlo (e risolverlo intendo mostrare il recyclerView popolato con gli elementi corretti proprio mentre lancio il frammento e aggiorno il recyclerView quando aggiungo più elementi alla lista)

Stiamo utilizzando un adpater personalizzato e un aggiornamento per ottenere dati dal server.

Ecco il codice

frammento che contiene il recyclerView

public class EventViewListFragment extends Fragment implements EventListAdapter.ClickListener{ 

    private RestClient restClient; 
    private Builder builder; 
    private String token ; 

    private boolean userScrolled = true; 
    int pastVisiblesItems, visibleItemCount, totalItemCount; 

    private LinearLayoutManager mLayoutManager; 

    private RecyclerView recyclerView; 
    private EventListAdapter eventListAdapter; 

    private Button btnNewEvent; 

    FloatingActionButton suggestFAB; 

    private int currentPage=1; 


    public EventViewListFragment(){ 
     restClient = new RestClient(); 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     System.out.println("Se llamo al onCreate de EventViewListFragment"); 
     super.onCreate(savedInstanceState); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     System.out.println("se llamo al onCreateView de EvENT List Fragment"); 
     // Inflate the layout for this fragment 
     View layout =inflater.inflate(R.layout.fragment_events_list, container, false); 
     setUpElements(layout); 
     addListeners(); 
     return layout; 
    } 

    private void setUpElements(View layout) 
    { 
     recyclerView = (RecyclerView) layout.findViewById(R.id.eventList); 
     eventListAdapter = new EventListAdapter(getActivity()); 
     eventListAdapter.setClickListener(this); 
     eventListAdapter.setData(getInitialData()); 
     recyclerView.setAdapter(eventListAdapter); 
     mLayoutManager=new LinearLayoutManager(getActivity()); 
     recyclerView.setLayoutManager(mLayoutManager); 
     suggestFAB = (FloatingActionButton) layout.findViewById(R.id.suggestFAB); 
     builder = new Builder(); 
    } 

    private void addListeners() 
    { 
     addNewEventListener(); 
     addScrollBottomListener(); 
    } 



    private void addNewEventListener() 
    { 
     /*btnNewEvent.setOnClickListener(new View.OnClickListener(){ 
      @Override 
      public void onClick(View view) 
      { 
       EventsActivity.getInstance().toNewEventForm(); 
      } 
     });*/ 

     suggestFAB.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View view) { 
       EventsActivity.getInstance().toNewEventForm(); 
       currentPage=1; 
      } 
     }); 
    } 

    public List<Event> getInitialData() 
    { 
     List<Event> data=new ArrayList<>(); 
     data = getEvents(data); 
     return data; 
    } 

    @Override 
    public void itemClicked(View view, int position) { 
     EventsActivity.getInstance().toEventPage(eventListAdapter.getItemAtPos(position)); 
     currentPage=1; 

    } 
    private void addScrollBottomListener() { 
     recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { 

      @Override 
      public void onScrollStateChanged(RecyclerView recyclerView, int newState) { 

       super.onScrollStateChanged(recyclerView, newState); 
       if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) { 
        userScrolled = true; 

       } 

      } 

      @Override 
      public void onScrolled(RecyclerView recyclerView, int dx, 
            int dy) { 

       super.onScrolled(recyclerView, dx, dy); 
       // Here get the child count, item count and visibleitems 
       // from layout manager 

       visibleItemCount = mLayoutManager.getChildCount(); 
       totalItemCount = mLayoutManager.getItemCount(); 
       pastVisiblesItems = mLayoutManager.findFirstVisibleItemPosition(); 
       if (userScrolled && (visibleItemCount + pastVisiblesItems) == totalItemCount) { 
        userScrolled = false; 

        addNewElementsToList(); 
       } 

      } 

     }); 

    } 

    private void addNewElementsToList() 
    { 
     Toast.makeText(getActivity(), "Cargando Mas Elementos", Toast.LENGTH_SHORT).show(); 
     eventListAdapter.setData(getEvents(eventListAdapter.getData())); 
    } 

    private List<Event> getEvents(final List<Event> eventsList) 
    { 
     System.out.println("Asignando CALL"); 
     Call<JsonElement> eventPage = restClient.getConsumerService().getEvents(token, "", currentPage, 10); 
     System.out.println("Enquequeing"); 
     eventPage.enqueue(new Callback<JsonElement>() { 
      @Override 
      public void onResponse(Response<JsonElement> response) { 
       JsonObject responseBody = response.body().getAsJsonObject(); 
       if (responseBody.has("events")) { 
        JsonArray jsonArray = responseBody.getAsJsonArray("events"); 
        System.out.println(jsonArray.size()); 
        for (int i = 0; i < jsonArray.size(); i++) { 
         JsonObject storedObject = jsonArray.get(i).getAsJsonObject(); 
         Event current = new Event(); 
         current.setEventId(storedObject.get("id").getAsInt()); 
         current.setName(storedObject.get("title").getAsString()); 
         Calendar startCal = new GregorianCalendar(); 
         startCal.setTimeInMillis((storedObject.get("starts_at").getAsLong()) * 1000); 
         current.setStartDateTime(startCal); 
         Calendar endCal = new GregorianCalendar(); 
         endCal.setTimeInMillis((storedObject.get("ends_at").getAsLong()) * 1000); 
         current.setFinishDateTime(endCal); 
         current.setImgUrl(storedObject.get("image").getAsString()); 
         eventsList.add(current); 
        } 
       } else { 
        if (responseBody.has("error")) { 
         System.out.println("ERROR"); 
         wan.wanmarcos.models.Error error = builder.buildError(responseBody.get("error").getAsJsonObject()); 
         Toast.makeText(getActivity(), "Error : " + error.toString(), Toast.LENGTH_SHORT).show(); 
        } else { 

        } 
       } 
      } 

      @Override 
      public void onFailure(Throwable t) { 
      } 
     }); 
     eventListAdapter.notifyDataSetChanged(); 
     currentPage++; 
     return eventsList; 
    } 
} 

adattatore personalizzato per RecyclerView

public class EventListAdapter extends RecyclerView.Adapter<EventListAdapter.EventListViewHolder>{ 
    private LayoutInflater inflater; 
    private List<Event> data = Collections.emptyList(); 
    private Context context; 
    private ClickListener clickListener; 

    public EventListAdapter(Context context){ 
     inflater = LayoutInflater.from(context); 
     this.context=context; 
    } 

    @Override 
    public EventListViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     View view = inflater.inflate(R.layout.event_list_item, parent, false); 
     EventListViewHolder holder = new EventListViewHolder(view); 
     return holder; 
    } 

    @Override 
    public void onBindViewHolder(EventListViewHolder holder, int position) { 
     System.out.println("se llamo al onBindViewHolder de ELA"); 
     Event current = getData().get(position); 
     holder.title.setText(current.getName()); 
     Picasso.with(context) 
       .load(current.getImgUrl()) 
       .into(holder.img); 
     String startDateAndTime = current.CalendarToString(current.getStartDateTime())+" - "+current.CalendarToString(current.getFinishDateTime()); 
     holder.dateAndTime.setText(startDateAndTime); 
    } 

    public void setClickListener(ClickListener clickListener){ 

     this.clickListener=clickListener; 
    } 

    @Override 
    public int getItemCount() { 

     return getData().size(); 
    } 

    public List<Event> getData() { 
     return data; 
    } 

    public void setData(List<Event> data) { 
     this.data = data; 
    } 

    class EventListViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { 

     TextView title; 
     TextView dateAndTime; 
     ImageView img; 

     public EventListViewHolder(View itemView) { 

      super(itemView); 
      itemView.setOnClickListener(this); 
      title = (TextView) itemView.findViewById(R.id.eventListTitle); 
      img = (ImageView) itemView.findViewById(R.id.eventListImage); 
      dateAndTime =(TextView) itemView.findViewById(R.id.eventListDateAndTime); 
     } 


     @Override 
     public void onClick(View v) { 

      if(clickListener!=null) 
      { 
       clickListener.itemClicked(v,getPosition()); 
      } 
     } 

    } 

    public Event getItemAtPos(int pos) 
    { 
     return getData().get(pos); 
    } 


    public interface ClickListener{ 
     public void itemClicked(View view,int position); 
    } 



} 

Fragment XML File

<?xml version="1.0" encoding="utf-8"?> 
<android.support.design.widget.CoordinatorLayout 
    android:id="@+id/main_content" 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent"> 

    <RelativeLayout 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" 
     tools:context="wan.wanmarcos.fragments.EventViewListFragment"> 

      <android.support.v7.widget.RecyclerView 
       android:id="@+id/eventList" 
       android:layout_width="match_parent" 
       android:layout_height="match_parent" 
       android:scrollbars="vertical" 
       > 
      </android.support.v7.widget.RecyclerView> 
    </RelativeLayout> 

    <android.support.design.widget.FloatingActionButton 
     android:id="@+id/suggestFAB" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_gravity="bottom|right" 
     app:layout_anchorGravity="bottom|right|end" 
     android:layout_margin="16dp" 
     android:clickable="true" 
     android:src="@mipmap/ic_add_white_48dp" /> 

</android.support.design.widget.CoordinatorLayout> 

risposta

5

eventsList nel vostro Activity e data nel vostro adattatore sono due diverse collezioni. Stai riempiendo il primo ma non il secondo. intialize data con new ArrayList<> invece di Collections.emptyList(); e poi aggiungere un metodo nel vostro adattatore, chiamare addAll, come quella:

public void addAll(final List<Event> new events) { 
     final int currentCount = data.size(); 
     synchronized(data) { 
     data.addAll(events); 
     } 
     if (Looper.getMainLooper() == Looper.myLooper()) { 
      notifyItemRangeInserted(currentCount, events.size()); 
     } else { 
      new Handler(Looper.getMainLooper()).post(new Runnable() { 
      @Override 
      public void run() { 
       notifyItemRangeInserted(currentCount, events.size()); 
      } 
      }); 
     } 
} 

il se i controlli altro se si chiama addAll dal thread UI o da un thread e la chiamata diverso notifyItemRangeInserted in modo sicuro. Nel Activity quando viene invocato il numero onResponse, dopo aver riempito completamente eventsList, basta chiamare il eventListAdapter.addAll(eventsList)

+0

Ha funzionato !!! Grazie mille, hai salvato me e i miei amici dal restare sveglio tutta la notte fino all'alba. Sei il migliore !!!! –

+0

siete i benvenuti – Blackbelt

+0

ha funzionato anche per me ... grazie mille .. – ELITE

Problemi correlati