Search code examples
androidandroid-recyclerviewandroid-viewholdergoogle-cloud-speech

RecyclerView update last position with continuous data


first of all when i'll get to my computer i will post code.

I'm trying to add and update the RecyclerViews from Speechrecognition data. For SpeechRecognition i'm using Google Cloud Speech I'm making a "Chat - view" every time the Speech is completed is adding the result to RecyclerView. I want to modify it by adding the new item as the onVoice() is recognized and update it as is recognizing the speech ( the result is still not final)

My approach was: as the SpeechRecognition is triggered by voice the new item is added (onVoiceStart) as the recognizers onVoice callback is triggered (new speech data chunk is recognized) i will delete the RecyclerViews last item and add the "chunk" to last position and after that calling adapter.notifyItemChanged(speechResults.size()-1)


Solution

  • Solution I :

         // Step 1: find the holder 
     RecyclerView.ViewHolder holder = recyclerView.findViewHolderForAdapterPosition(speechResults.size() - 1);
    
         //   Step 2: Check if the holder is not null and if has itemView .
        if (holder != null) {
    
            if (holder.itemView != null) {
                // from itemview find the TextView  and set the desired text :
                if (holder.getAdapterPosition() == speechResults.size() - 1) {
                    ((TextView) holder.itemView.findViewById(R.id.speech_sent_textView))
                            .setText(text);
                }
            }
     // Now update the adapter item also but do not notify the adapter change.
    

    Solution II : Using library LastAdapter

    1. Add Dependecy -> follow this

    2. in the Layout add new the root tag "< layout"

                  //Delte the space after "<"
        < layout xmlns:android="http://schemas.android.com/apk/res/android">
      
      <data>
          <variable name="item" type="com.github.nitrico.lastadapterproject.item.Header"/>
      </data>
      
      <TextView
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
      
          // you use  like thius "@{youritem.speecSent"
          android:text="@{item.text}"/>
          //Delte the space after "< "
       < /layout>
      

      NOTE: for using multiple layouts the data tag must have same variable name.

         <data>   
             // this name has to be same in every xml layout types.
          <variable name="item" type="com.github.nitrico.lastadapterproject.item.Header"/>
          </data>
      
    3. Java part: NOTE : listOfItems must be Observable ArrayList

        speechResults = new ObservableArrayList<>();
           ...
          new LastAdapter(speechResults , BR.item)
         .map(SpeechResult.class, R.layout.speech_sent)
         .map(SpeechResult.class, R.layout.speech_received)
         .into(recyclerView);
      

    BR.item - > you have to enable the databinding in build Gradle. the .item - > is the name given in the layout for data (that has to be same)

    if you want to handle the LayoutType using the same Item type (Class)

                new LastAdapter(speechResults, BR.item )
                .map(SpeechResult.class, R.layout.speech_sent_content)
                .map(SpeechResult.class, R.layout.speech_received_content)
                  .handler(new TypeHandler() {
                      @Nullable
                      @Override
                      public BaseType getItemType(Object o, int i) {
                          if(((SpeechResult) o).getSpeechType()==SpeechResult.SPEECH_TYPE_SENT){
                              return new BaseType(R.layout.speech_sent_content);
                          }
                          return new BaseType(R.layout.speech_received_content);
                      }
                  })
    
                .into(recyclerView);
    

    to adding new items in the recyclerView simply add item to your itemlist. LastAdapter will handle the refresh of data.