1

I was trying to make a RecyclerView which generates items on scroll. method >onScrollListener generates items with two different view types: ViewType == >FALSE creates a layout with a CardView on the right while ViewType == TRUE a >layout with CardView on the left.

what I was trying to achieve is to generate, using a loop, an infinite list of >items with odd items (with an int variable which increases every time an item is >generated) get positioned in layout CardView Right side otherwise in the layout >with CardView on the left.

example : [example_screenshot][1]

EDIT: forgot to add some code inside Adapter constructor! Added Log


Adapter

public class Adapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

List<Tipo> lista;
private int visibleThreshold = 14;
private int lastVisibleItem, totalItemCount;
private OnLoadMoreListener onLoadMoreListener;
private boolean loading;

public Adapter(List<Tipo> lista,RecyclerView recyclerView) {
    this.lista = lista;


//Forgot to add this part on the original question!

if(recyclerView.getLayoutManager() instanceof LinearLayoutManager){
final LinearLayoutManager linearLayoutManager =  
(LinearLayoutManager)recyclerView.getLayoutManager();
        recyclerView.addOnScrollListener(

                new RecyclerView.OnScrollListener() {

                    @Override
             public void onScrolled(RecyclerView recyclerView, int dx,int dy){
                      super.onScrolled(recyclerView, dx, dy);
                      totalItemCount = linearLayoutManager.getItemCount();
                      lastVisibleItem = 
                      linearLayoutManager.findLastVisibleItemPosition();
                      if(!loading && totalItemCount <= (lastVisibleItem + 
                      visibleThreshold)){
                         if(onLoadMoreListener != null){
                            onLoadMoreListener.onLoadMore();
                         }
                      loading = true;
                }
            }


        });
    }

//New part ended
    }
}



public void setLoaded() {
    loading = false;
}




public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener){
    this.onLoadMoreListener = onLoadMoreListener;
}

public interface OnLoadMoreListener {
    void onLoadMore();
}

@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View v;
    switch(viewType) {
        case 0:
            v = LayoutInflater.from(parent.getContext()).inflate(R.layout.elemento_destro,parent,false);
            return new ViewHolder1(v);
        case 1:
            v = LayoutInflater.from(parent.getContext()).inflate(R.layout.elemento_sinistro,parent,false);
            return new ViewHolder2(v);

    }
    return null;
}

@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder,  
int position) {

    Tipo oggetto = lista.get(position);
    if(oggetto != null)
    {
        if(oggetto.getType())
        {((ViewHolder1)viewHolder).titolo1.setText(oggetto.getName());}
        else
        {((ViewHolder2)viewHolder).titolo2.setText(oggetto.getName()); }
    }
}

@Override
public int getItemCount() {
    if (lista == null)
        return 0;
    return lista.size();
}

public int getItemViewType(int position){
    if (lista.get(position).DIREZIONE)
    {
       return 0;
    }
    else {return 1;}
}

View Holder right item

class ViewHolder1 extends  RecyclerView.ViewHolder implements View.OnClickListener{

private TextView titolo1;
public ViewHolder1(@NonNull View itemView) {
    super(itemView);
    titolo1 = itemView.findViewById(R.id.testoDestro);
}

@Override
public void onClick(View v) {

}
}

View Holder left item

class ViewHolder2 extends RecyclerView.ViewHolder implements View.OnClickListener{

private TextView titolo2;
public ViewHolder2(@NonNull View itemView) {
    super(itemView);
    titolo2 = itemView.findViewById(R.id.testoSinistro);
}

@Override
public void onClick(View v) {

}
}

Main

public class MainActivity extends AppCompatActivity {

private List<Tipo> lista;
private List<String> lista2;
ImageView indietro;
Handler handler = new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    RecyclerView recyclerView;

    LinearLayoutManager linearLayoutManager;
    linearLayoutManager = new LinearLayoutManager(MainActivity.this);

    recyclerView = (findViewById(R.id.recycler));
    indietro = findViewById(R.id.indietro);

    recyclerView.setLayoutManager(linearLayoutManager);
    final Adapter adapter = new Adapter(Dati.getData(), recyclerView);
    recyclerView.setAdapter(adapter);


    recyclerView.setLayoutManager(linearLayoutManager);
    recyclerView.setAdapter(adapter);


    adapter.setOnLoadMoreListener(new Adapter.OnLoadMoreListener() {
        @Override
        public void onLoadMore() {
            lista.add(null);
            adapter.notifyItemInserted(lista.size() - 1);
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    lista.remove(lista.size() - 1);
                    adapter.notifyItemRemoved(lista.size());
                    for (int i = 0; i < 15; i++) {
                        if (i % 2 == 1) {
                            lista.add(new Tipo("Example",false));
                            adapter.notifyItemInserted(lista.size());
                        }
                        else{
                            lista.add(new Tipo("Example",true));
                            adapter.notifyItemInserted(lista.size());
                        }

                    }
                    adapter.setLoaded();
                }
            }, 3000);
            System.out.println("load");
        }
    });



   }

}

Log

2019-05-03 10:08:25.249 5254-5254/? I/o.myapplicatio: Late-enabling -Xcheck:jni
2019-05-03 10:08:25.469 5254-5254/com.sinfo.myapplication W/o.myapplicatio: JIT profile information will not be recorded: profile file does not exits.
2019-05-03 10:08:25.472 5254-5254/com.sinfo.myapplication I/chatty: uid=10122(com.sinfo.myapplication) identical 10 lines
2019-05-03 10:08:25.472 5254-5254/com.sinfo.myapplication W/o.myapplicatio: JIT profile information will not be recorded: profile file does not exits.
2019-05-03 10:08:25.499 5254-5254/com.sinfo.myapplication I/InstantRun: starting instant run server: is main process
2019-05-03 10:08:25.720 5254-5254/com.sinfo.myapplication W/o.myapplicatio: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (light greylist, reflection)
2019-05-03 10:08:25.722 5254-5254/com.sinfo.myapplication W/o.myapplicatio: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (light greylist, reflection)
2019-05-03 10:08:25.969 5254-5254/com.sinfo.myapplication D/OpenGLRenderer: Skia GL Pipeline
2019-05-03 10:08:26.073 5254-5272/com.sinfo.myapplication I/Adreno: QUALCOMM build                   : a570411, Id0218a7f5c
Build Date                       : 09/27/18
OpenGL ES Shader Compiler Version: EV031.25.03.00
Local Branch                     : 
Remote Branch                    : refs/tags/AU_LINUX_ANDROID_LA.UM.7.5.R1.09.00.00.464.025
Remote Branch                    : NONE
Reconstruct Branch               : NOTHING
2019-05-03 10:08:26.073 5254-5272/com.sinfo.myapplication I/Adreno: Build Config                     : S L 6.0.7 AArch64
2019-05-03 10:08:26.083 5254-5272/com.sinfo.myapplication I/Adreno: PFP: 0x005ff110, ME: 0x005ff066
2019-05-03 10:08:26.089 5254-5272/com.sinfo.myapplication I/ConfigStore: android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasWideColorDisplay retrieved: 0
2019-05-03 10:08:26.089 5254-5272/com.sinfo.myapplication I/ConfigStore: android::hardware::configstore::V1_0::ISurfaceFlingerConfigs::hasHDRDisplay retrieved: 1
2019-05-03 10:08:26.090 5254-5272/com.sinfo.myapplication I/OpenGLRenderer: Initialized EGL, version 1.4
2019-05-03 10:08:26.090 5254-5272/com.sinfo.myapplication D/OpenGLRenderer: Swap behavior 2
2019-05-03 10:08:26.127 5254-5254/com.sinfo.myapplication W/o.myapplicatio: Accessing hidden field Landroid/view/View;->mAccessibilityDelegate:Landroid/view/View$AccessibilityDelegate; (light greylist, reflection)
2019-05-03 10:08:46.624 5254-5254/com.sinfo.myapplication W/ActivityThread: handleWindowVisibility: no activity for token android.os.BinderProxy@e5efecf
2019-05-03 10:08:48.664 5254-5254/com.sinfo.myapplication D/AndroidRuntime: Shutting down VM
2019-05-03 10:08:48.672 5254-5254/com.sinfo.myapplication E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.sinfo.myapplication, PID: 5254
java.lang.NullPointerException: Attempt to invoke interface method 'boolean java.util.List.add(java.lang.Object)' on a null object reference
    at com.sinfo.myapplication.MainActivity$1.onLoadMore(MainActivity.java:53)
    at com.sinfo.myapplication.Adapter$1.onScrolled(Adapter.java:43)
    at android.support.v7.widget.RecyclerView.dispatchOnScrolled(RecyclerView.java:4961)
    at android.support.v7.widget.RecyclerView$ViewFlinger.run(RecyclerView.java:5117)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:949)
    at android.view.Choreographer.doCallbacks(Choreographer.java:761)
    at android.view.Choreographer.doFrame(Choreographer.java:693)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:935)
    at android.os.Handler.handleCallback(Handler.java:873)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:6718)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Mike-OS
  • 103
  • 11

1 Answers1

0

I believe your issue is with how you're notifying your adapter. If you don't notify it correctly, that will cause an inconsistency between the adapter and the data and the app will crash.

For example, if you remove all the items, but instead tell the adapter you've added more - that will lead to a crash.

In your code, you're adding items and telling it two different positions.

lista.add(null);
adapter.notifyItemInserted(lista.size() - 1);

and

lista.add(new Tipo("Example",false));
adapter.notifyItemInserted(lista.size());

You're telling the adapter where you've inserted the new item, but in these you're telling it two different positions (.size() and .size() - 1).

Advice-Dog
  • 4,481
  • 6
  • 29
  • 53
  • I have realized that I have forgotten to upload a part code inside the Adapter constructor. also, log has been uploaded. – Mike-OS May 03 '19 at 08:55