RecyclerView scrolling laggy on newer android versions - android

My RecyclerView is pretty laggy whenever I start to scroll over the first items in a cold app start. This behavior happens for the latest android versions (tested on API level 27 and 28) but not older ones (tested on API level 22).
I tried both versions, the normal com.android.support:appcompat-v7:28.0.0 and androidx com.google.android.material:material:1.1.0-alpha03.
The test project is pretty simple:
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recyclerView = findViewById(R.id.recyclerview);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
recyclerView.setItemViewCacheSize(20);
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < 200; i++) {
list.add(String.valueOf(i));
}
MyAdapter adapter = new MyAdapter(MainActivity.this, list);
recyclerView.setAdapter(adapter);
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
MyAdapter.java
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
List<String> mData;
Context context;
LayoutInflater mInflater;
public MyAdapter(Context context, List<String> data) {
this.mData = data;
this.context = context;
this.mInflater = LayoutInflater.from(context);
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = mInflater.inflate(R.layout.recycler_item, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder viewHolder, int i) {
viewHolder.tv.setText(String.valueOf(i));
}
#Override
public int getItemCount() {
return mData.size();
}
public String getItem(int id) {
return mData.get(id);
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView tv;
public ViewHolder(#NonNull View itemView) {
super(itemView);
tv = itemView.findViewById(R.id.item_tv);
}
}
}
recycler_item.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
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="wrap_content"
xmlns:tools="http://schemas.android.com/tools">
<TextView
android:id="#+id/item_tv"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
Any ideas for solving the problem or is it a library issue which can't be solved by myself (waiting for new official release)?

In you item layout the wrapper class is ConstraintLayout with wrap_content_height - it could cause problems while measuring.
Since you have a single itme inside you could just get rid of wrapper and keep just single TextView as a root element
If you still wants to get wrapper for the view - try to avoid wrap_content for RelativeLayout and/or ConstrainLayout, use fix size or simple layouts such as Frame/Linear.

get layoutInflaterfrom parent context so instead of
mInflater.inflate(R.layout.recycler_item, viewGroup, false);
use this
LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item, viewGroup,
false);
Hope this will help

I solved the problem by setting the build variant to release after finding this comment: Performance of ConstraintLayout inside RecyclerView ViewHolder.
The example shared here is smoothly then and my application with Glide performs more smoothly, too, even without setting layout_width to ConstraintLayout.
But it's unclear to me why this lag appears in the debug mode and only on the latest android versions.

I was facing same problem and solved by using recyclerview within nested scroll view. like below code:
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbarSize="5dp"
android:scrollbars="vertical"
android:layout_above="#id/ListBannerAds">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical"
android:scrollbarSize="5dp"
android:nestedScrollingEnabled="false"
android:id="#+id/ZaboorListRecyclerview"/>
</androidx.core.widget.NestedScrollView>

Related

How do I not recycle only the first 2 views of my recyclerview or any items?

I am using a recyclerview for displaying and broadcasting videos of users. However, when I scroll through the recycler view, I see my first view, which has my video gets recycled hence why it's not visible to other users. Is there a way I can make sure that the first view is not recycled so I dont have to worry about my video view getting resetrecycled every single time I scroll through my list?
Here's my code :
In my fragment...
...
<android.support.v7.widget.RecyclerView
android:id="#+id/videoList"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="invisible"
app:layout_constraintBottom_toTopOf="#+id/myButtonContainer"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/myoldContainer">
...
and the corresponding adapter...
public class GroupAdapter extends RecyclerView.Adapter<GroupAdapter.myViewHolder> {
private CopyOnWriteArrayList<Person> persons;
private Context mContext;
public GroupAdapter(#NonNull final CopyOnWriteArrayList<Person> persons , Context context) {
this.persons = persons;
this.mContext= context;
for (Person person : this.persons) {
//get names
}
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final View layout = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_person, parent, false);
final MyViewHolder viewHolder = new MyViewHolder(layout);
return viewHolder;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
final Person person = person.get(position);
final Participant participant = person.getParticipant();
if (person.getName() != null) {
holder.personName.setText(person.getName());
}
if (person.getImage() != null) {
holder.personImage.setImageBitmap(person.getImage());
} else {
holder.personImage.setImageResource(R.drawable.default_profile);
}
holder.personImage.setVisibility(View.INVISIBLE);
holder.personImage.setVisibility(View.VISIBLE);
final VideoView videoView;
if (participant.isMe) {
videoView = participant.videoStreamer.videoView;
} else {
videoView = participant.videoPlayer.videoView;
}
if (holder.personVideo.getChildCount() != 0) {
holder.personVideo.removeAllViews();
}
if (videoView.getParent() != null) {
ViewGroup parent = (ViewGroup) videoView.getParent();
parent.removeView(videoView);
}
holder.personVideo.addView(videoView, myViewHolder.videoLayoutParams);
if (person.isVideoPaused()) {
holder.personVideo.setVisibility(View.INVISIBLE);
holder.personImage.setVisibility(View.VISIBLE);
} else {
holder.personVideo.setVisibility(View.VISIBLE);
holder.personImage.setVisibility(View.INVISIBLE);
}
}
#Override
public int getItemCount() {
return persons.size();
}
public static final class MyViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.personVideo)
public ViewGroup personVideo;
#BindView(R.id.personImage)
public ImageView personImage;
#BindView(R.id.personName)
public TextView personName;
protected static FrameLayout.LayoutParams videoLayoutParams = new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
);
public MyViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}
Here's how I am setting it in my fragment:
LinearLayoutManager manager = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);
videoAdapter = new VideoAdapter(myHelper.getPeople(), getContext());
videoList.setLayoutManager(manager);
videoList.setAdapter(videoAdapter);
item_person:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginTop="0dp"
android:background="#drawable/person_border"
xmlns:app="http://schemas.android.com/apk/res-auto">
<RelativeLayout
android:id="#+id/personContainer"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent">
<FrameLayout
android:id="#+id/personVideo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/black" />
<ImageView
android:id="#+id/personImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/black"
android:src="#drawable/default_profile" />
<TextView
android:id="#+id/personName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#AA555555"
android:gravity="center_horizontal|bottom"
android:textColor="#color/green"
android:textSize="12sp"
android:lines="1"
android:ellipsize="end"
tools:text="androiduser#gmail.com"
android:layout_alignParentBottom="true" />
</RelativeLayout>
</android.support.constraint.ConstraintLayout>
fragment with recycle view: xml
<android.support.constraint.ConstraintLayout 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">
<RelativeLayout>
....
</RelativeLayout>
<include containers>...</include>
...
<android.support.v7.widget.RecyclerView
android:id="#+id/personList"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="invisible"
>
</android.support.v7.widget.RecyclerView>
</android.support.constraint.ConstraintLayout>
I don't think that "not recycling" the video view will actually stop it from being destroyed when you scroll. It's not the recycling is the problem but the view unbinding.
I think such complex component such as VideoView should not be inside the RecyclerView at all.. You can try adding it as a static content on top, which most likely will solve the issue. You can use a NestedScrollView for that. Take a look here: Recyclerview inside scrollview- How to scroll whole content?
If you still think you want to keep it in the RecyclerView and disable the recycling, do the following.
Create a separate view type for your video view items. Here is an example:
https://stackoverflow.com/a/26573338/3086818. Treat your video view item as a header view from the example.
Once you do this, there is a RecycledViewPool class which manages the recycling of items inside a RecyclerView. You can tell it which views to recycle and which not. By default it recycles all views. To disable recycling for your video view items use your new view type like this:
recyclerView.getRecycledViewPool().setMaxRecycledViews(TYPE_VIDEO_VIEW, 0);
where TYPE_VIDEO_VIEW is the new type that you created using the previous example. The number 0 tells the RecyclerView how many items to recycle - in this case it's 0, meaning "do not recycle". More info about this here: https://stackoverflow.com/a/36313437/3086818.
I hope this helps.. Good luck!
The answer is yes, you can actually do that.
Since you said "The first item" so you simply add a check.
if(position == 0)
{
holder.setIsRecyclable(false); //This line prevents the row from recycling
}

RecyclerView not displaying elements from list

I've tried creating a RecyclerView which displays the songs I have on my phone from a pre-populated ArrayList. Here is my code for my activity:
public class HomeActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
private RecyclerView songRecyclerView;
private RecyclerView.Adapter songRecyclerAdapter;
private RecyclerView.LayoutManager recyclerLayoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
//get the songs list for the adapter
ArrayList<Audio> songList;
StorageUtils storageUtils = new StorageUtils(getApplicationContext());
songList = storageUtils.loadAudio();
//Recycler view setup for songs display
songRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
songRecyclerView.setHasFixedSize(true);
recyclerLayoutManager = new LinearLayoutManager(this);
songRecyclerView.setLayoutManager(recyclerLayoutManager);
songRecyclerAdapter = new SongAdapter(songList);
songRecyclerView.setAdapter(songRecyclerAdapter);
}
The Audio class has the getTitle() and getArtist() methods, which do work. The loud audio() also works so Songlist definitely has elements in it.
Here is the xml of the recyclerview item:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/recycler_item"
android:layout_width="match_parent"
android:layout_height="72dp"
android:visibility="visible">
<TextView
android:id="#+id/recycler_item_songName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:text="song name"
android:textColor="#color/textPrimary"
android:textSize="16sp"
android:textStyle="normal"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/recycler_item_artistName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
android:text="song artist"
android:textColor="#color/textSecondary"
android:textSize="16sp"
android:textStyle="normal"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/recycler_item_songName" />
</android.support.constraint.ConstraintLayout>
Here is my implementation of the Adapter:
package com.ecebuc.gesmediaplayer;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
public class SongAdapter extends RecyclerView.Adapter<SongAdapter.ViewHolder> {
// The dataset
private ArrayList<Audio> songList;
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView recyclerTitleView, recyclerArtistView;
public ViewHolder(View itemView) {
super(itemView);
this.recyclerTitleView = (TextView) itemView.findViewById(R.id.recycler_item_songName);
this.recyclerArtistView = (TextView) itemView.findViewById(R.id.recycler_item_artistName);
}
}
// Constructor
public SongAdapter(ArrayList<Audio> songList){
this.songList = songList;
}
#Override
public SongAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// create a new view
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View listItemView = layoutInflater.inflate(R.layout.song_list_item, parent, false);
ViewHolder viewHolder = new ViewHolder(listItemView);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Audio currentSong = songList.get(position);
holder.recyclerTitleView.setText(currentSong.getTitle());
holder.recyclerArtistView.setText(currentSong.getArtist());
Log.d("onBind: ", (String)holder.recyclerTitleView.getText() + (String)holder.recyclerArtistView.getText());
}
#Override
public int getItemCount() {
return songList.size();
}
}
The frustrating thing is that at my very first attempt at creating the whole recycleView, it did work and displayed the text. I tried adding an imageView as the cover of the songs to the layout of each item in the list, and the code to display that as well, and it wasn't working anymore. When tried to revert and have only the code for text, it stopped working altogether.
I am bashing my head over this because if I did make some small change somewhere, I don't know where it might be any more now. But I did try to recreate the class for the adapter and the layout file for the whole recycler functionality from scratch, and still not showing. The layout items have to be there because I see the shadow of the scroll.
Also, in the adapter's onBindViewHolder, that Log.d displays correctly each song title and artist. And it calls the newly created views' getText(). It's like the text was white. And no, the values of #color/text primary and textSecondary in the XML are #212121 and #424242 and were always like that (again, it did display the values the first time, and I haven't touched the colours).
I've looked for similar problems on StackOverflow and online, but I don't seem to have that kind of mistakes. I don't know what to do anymore. Heck, I'll even include the XML of the screen that has the actual recyclerView in it. At this point I don't know what could make those views invisible:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".HomeActivity"
tools:showIn="#layout/app_bar_home">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
Finally, I thought of looking at the developer options on my phone and display layout outlines, and this is what I had...as if the two textViews are not being created, yet I was able to get their text content after I've set it, so how is that even possible? Thank you to whoever can help me, I'm just trying to learn here...
For future reference in case anyone has a similar problem, I managed to solve it by simply changing my constraint layout in the recycler view item XML, to linear layout (or I'd guess whatever type of layout other than constraint) and compiled.
It worked well, displaying everything correctly. Then changing the XML back to constraint layout like before, and everything was still working fine. At this point I'd say it will forever remain a mystery.
make some change in adapter constructor like below code..
public Context context;
// Constructor
public SongAdapter(Context context,ArrayList<Audio> songList){
this.context=context;
this.songList = songList;
}
then after main activity make adapter object like below ..
SongAdapter adapter;
and remove this line of code ..
private RecyclerView.Adapter songRecyclerAdapter;
and used set adapter like below code..
RecyclerView recyclerView;
SongAdapter songRecyclerAdapter;
private void setAdapter(){
recyclerView.setLayoutManager(new LinearLayoutManager(this));
if (songRecyclerAdapter==null) {
songRecyclerAdapter = new SongAdapter(this,songList);
recyclerView.setAdapter(songRecyclerAdapter);
songRecyclerAdapter.notifyDataSetChanged();
}
else{
songRecyclerAdapter.notifyDataSetChanged();
}
}

Wrong dimension on recyclerview grid first row

I am trying to list items on my recycler view using the grid layout manager with two columns.
However, the first row of the grid seems to be having width issues.
When I scroll down until the first row is invisible, then scrolled back up, it will fix itself and show the correct width.
My items are retrieved from themoviedb API,
adapter.setMovieWrapper(body); // body contains data from the API
recyclerView.setLayoutManager(new GridLayoutManager(this, 2));
recyclerView.setAdapter(adapter);
Here is the layout code for the grid item:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="200dp"
android:padding="2dp"
android:orientation="vertical">
<ImageView
android:id="#+id/movie_thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerInside"
android:contentDescription="#string/movie_thumbnail_description"/>
<TextView
android:background="#drawable/bg_shade"
android:id="#+id/movie_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:textColor="#FFF"
android:ellipsize="end"
android:padding="8dp"/>
</FrameLayout>
Here is the adapter code:
public class MovieGridAdapter extends RecyclerView.Adapter<MovieGridItemViewHolder> {
MovieWrapper movieWrapper;
private Context context;
public MovieGridAdapter(Context context) {
this.context = context;
}
public MovieWrapper getMovieWrapper() {
return movieWrapper;
}
public void setMovieWrapper(MovieWrapper movieWrapper) {
this.movieWrapper = movieWrapper;
this.notifyDataSetChanged();
}
#Override
public MovieGridItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new MovieGridItemViewHolder(
LayoutInflater.from(context)
.inflate(R.layout.movie_grid_item, parent, false)
);
}
#Override
public void onBindViewHolder(MovieGridItemViewHolder holder, int position) {
Movie movie = movieWrapper.getResults().get(position);
Uri uri = Uri.parse("https://image.tmdb.org/t/p/w185");
uri = uri.buildUpon().appendEncodedPath(movie.getPosterPath()).build();
Picasso.with(context)
.load(uri)
.into(holder.getThumbnail());
holder.getTitle().setText(movie.getTitle());
}
#Override
public int getItemCount() {
if (movieWrapper != null && movieWrapper.getResults() != null) {
return movieWrapper.getResults().size();
}
return 0;
}
}
and here is the activity that host the recycler view XML layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.adityapurwa.popularmovies.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/movie_grid"
android:layout_width="match_parent"
android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>
</android.support.constraint.ConstraintLayout>
Anyone know what is causing this issue and how to resolve it?
Thanks!
There seems to be an issue with my ConstraintLayout hosting the RecyclerView, I changed it to FrameLayout and the issue disappeared. Even though the layout and the RecyclerView both have its dimension set to match_parent, somehow it fails to detect the dimension.
Note: Changing the dimension to be absolute (e.g 100dp) also solved the problem, however it makes the layout unresponsive.
I have used FrameLayout around Recyclerview but did not work, I used this work around solution like this, for first 2 items i added dummy items and hidden the views, this worked for me , although this is not a perfect solution

DataBinding: How to create RecyclerView Adapter with same model and different layout?

I use same adapter for two different item layouts. One is for grid, one is for linear display. I'm passing layout id with itemLayout to adapter. However, I wasn't able to add data binding properly. Could you help me out, please?
Here is my adapter effort so far:
public class OyuncuAdapter extends RecyclerView.Adapter<OyuncuAdapter.ViewHolder> {
ArrayList<Oyuncu> oyuncuListesi;
Context context;
int itemLayout;
public OyuncuAdapter(ArrayList<Oyuncu> oyuncuListesi, Context context, int itemLayout) {
this.oyuncuListesi = oyuncuListesi;
this.context=context;
this.itemLayout = itemLayout;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(context).inflate(itemLayout, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Oyuncu oyuncu = oyuncuListesi.get(position);
holder.binding.setVariable(BR.oyuncu, oyuncu);
holder.binding.executePendingBindings();
}
#Override
public int getItemCount() {
return oyuncuListesi.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder{
private ViewDataBinding binding;
public ViewHolder(View itemView) {
super(itemView);
binding = DataBindingUtil.bind(itemView);
}
}
}
Here is the item layout:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="oyuncu"
type="com.figengungor.suits.model.Oyuncu" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical"
android:padding="#dimen/itemPadding"
tools:background="#color/darkgrey">
<ImageView
android:id="#+id/foto"
android:layout_width="150dp"
android:layout_height="150dp"
android:gravity="center"
android:scaleType="centerCrop"
app:imageResource="#{oyuncu.foto}"
tools:src="#drawable/gabrielmacht" />
<TextView
android:id="#+id/isim"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="#android:color/white"
android:text="#{oyuncu.isim}"
tools:text="Gabriel Macht" />
</LinearLayout>
</layout>
The error I'm getting is not really helpful:
Caused by: java.lang.RuntimeException: view tag isn't correct on view:null
My bad. This part works perfectly. My problem is extending BaseActivity which also uses DataBinding. The crash is related to that. After removing extending BaseActivity from my activity, it worked. However, I opened another question realted to that. If you could look at that, I'll be grateful. DataBinding: How to use BaseActivity

RecyclerView scrolling issue (Child items far away from each other)

Goodd day.I have simple recycler view with simplest dummy datas for test purpose,thus i have an weird issue to which the google did not find any solution or even an issue at all.On first launch the view is all good but as soon as i start to scrool,the child items are being as far from each other as no one can image...Really very and very far.But the issue is that the actual child items layout parameters are correct,only issue is that i dont know why RecyclerView decides to have each item heaps far away from each other.Please can you give me an help?Posting full code of my RecyclerView.
The view for recyclerView
<?xml version="1.0" encoding="utf-8"?>
<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"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="com.ink.activities.HomeActivity"
tools:showIn="#layout/app_bar_home">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical" />
</RelativeLayout>
The Adapter.
public class FeedAdapter extends RecyclerView.Adapter<FeedAdapter.ViewHolder> {
private List<FeedModel> feedList;
private Context mContext;
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView title, content;
public ViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.feedTitle);
content = (TextView) view.findViewById(R.id.feedContent);
}
}
public FeedAdapter(List<FeedModel> feedList, Context context) {
mContext = context;
this.feedList = feedList;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.feed_single_view, parent, false);
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
FeedModel feedModel = feedList.get(position);
holder.title.setText(feedModel.getTitle());
holder.content.setText(feedModel.getContent());
// animate(holder);
}
public void animate(RecyclerView.ViewHolder viewHolder) {
final Animation animAnticipateOvershoot = AnimationUtils.loadAnimation(mContext, R.anim.bounce_interpolator);
viewHolder.itemView.setAnimation(animAnticipateOvershoot);
}
#Override
public int getItemCount() {
return feedList.size();
}
}
I guess you won`t need holder as no view initiated with it.
The single child item view of RecyclerView adapter.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:clickable="true"
android:foreground="?android:attr/selectableItemBackground"
app:cardCornerRadius="5dp"
app:cardElevation="10dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/feedTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="10dp"
android:fontFamily="#string/appFont"
android:text="loading...."
android:textColor="#000000"
android:textSize="20sp" />
<TextView
android:id="#+id/feedContent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/feedTitle"
android:layout_marginLeft="2dp"
android:layout_marginRight="2dp"
android:layout_marginTop="10dp" />
</RelativeLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
The initiation of actual parameters.
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mAdapter = new FeedAdapter(mFeedModelArrayList, this);
RecyclerView.ItemAnimator itemAnimator = new DefaultItemAnimator();
itemAnimator.setAddDuration(500);
itemAnimator.setRemoveDuration(500);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setItemAnimator(itemAnimator);
This code is as simple as it can get and it is important to mention that i am initiation all this inside the default NAVIGATION DRAWER ACTIVITY of android studio (the default templae inside content_main layout).So plaese can you give me any hint about the issue?
You're using
android:layout_width="match_parent"
android:layout_height="match_parent"
on your child item views. As of Support Library 23.2:
The RecyclerView widget provides an advanced and flexible base for creating lists and grids as well as supporting animations. This release brings an exciting new feature to the LayoutManager API: auto-measurement! This allows a RecyclerView to size itself based on the size of its contents. This means that previously unavailable scenarios, such as using WRAP_CONTENT for a dimension of the RecyclerView, are now possible. You’ll find all built in LayoutManagers now support auto-measurement.
Due to this change, make sure to double check the layout parameters of your item views: previously ignored layout parameters (such as MATCH_PARENT in the scroll direction) will now be fully respected.
Change your layout_height to wrap_content if you only want your items to be as large as needed. match_parent means they will be as large as the screen.

Categories

Resources