recyclerview sans adaptateur; aménagement de saut
vient d'implémenter Recyclerview dans mon code, remplaçant Listview.
tout fonctionne très bien. Les objets sont affichés.
mais logcat dit
15: 25:53.476 E / RecyclerView"
15: 25:53.655 E / RecyclerView"
pour le code
ArtistArrayAdapter adapter = new ArtistArrayAdapter(this, artists);
recyclerView = (RecyclerView) findViewById(R.id.cardList);
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
comme vous pouvez le voir, j'ai joint un adaptateur pour Recycleview . alors pourquoi j'obtiens cette erreur?
j'ai lu d'autres questions liées au même problème, mais aucune aide.
24 réponses
pouvez-vous vous assurer que vous appelez ces déclarations à partir du fil" principal "(par exemple à l'intérieur de la méthode onCreate()
).
Dès que j'appelle les mêmes déclarations d'une méthode "retardée". Dans mon cas, un ResultCallback
, je reçois le même message.
dans mon Fragment
, appelant le code ci-dessous de l'intérieur d'une méthode ResultCallback
produit le même message. Après avoir déplacé le code vers la méthode onConnected()
dans mon application, le message a disparu...
LinearLayoutManager llm = new LinearLayoutManager(this);
llm.setOrientation(LinearLayoutManager.VERTICAL);
list.setLayoutManager(llm);
list.setAdapter( adapter );
je recevais les mêmes deux messages d'erreur jusqu'à ce que je corrige deux choses dans mon code:
(1) par défaut, lorsque vous implémentez des méthodes dans le RecyclerView.Adapter
il génère:
@Override
public int getItemCount() {
return 0;
}
assurez-vous de mettre à jour votre code pour qu'il dise:
@Override
public int getItemCount() {
return artists.size();
}
évidemment si vous avez zéro articles dans vos articles, alors vous obtiendrez zéro choses affichées sur l'écran.
(2) Je ne faisais pas cela comme indiqué dans le haut de la page réponse: CardView layout_width=" match_parent "does not match parent RecyclerView width "1519170920
//correct
LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_listitem, parent, false);
//incorrect (what I had)
LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_listitem,null);
(3) EDIT: BONUS:
Assurez-vous également de configurer votre RecyclerView
comme ceci:
<android.support.v7.widget.RecyclerView
android:id="@+id/RecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
pas comme ceci:
<view
android:id="@+id/RecyclerView"
class="android.support.v7.widget.RecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
j'ai vu quelques tutoriels utilisant cette dernière méthode. Bien que cela fonctionne, je pense qu'il génère cette erreur.
j'ai la même situation avec vous, l'affichage est ok, mais l'erreur apparaît dans le locat. C'est ma solution: (1) initialiser L'adaptateur RecyclerView & bind sur CREATE ()
RecyclerView mRecycler = (RecyclerView) this.findViewById(R.id.yourid);
mRecycler.setAdapter(adapter);
(2) call notifydatastatatechanged when you get the data""
adapter.notifyDataStateChanged();
dans le code source de recyclerView, il y a un autre thread pour vérifier l'état des données.
public RecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.mObserver = new RecyclerView.RecyclerViewDataObserver(null);
this.mRecycler = new RecyclerView.Recycler();
this.mUpdateChildViewsRunnable = new Runnable() {
public void run() {
if(RecyclerView.this.mFirstLayoutComplete) {
if(RecyclerView.this.mDataSetHasChangedAfterLayout) {
TraceCompat.beginSection("RV FullInvalidate");
RecyclerView.this.dispatchLayout();
TraceCompat.endSection();
} else if(RecyclerView.this.mAdapterHelper.hasPendingUpdates()) {
TraceCompat.beginSection("RV PartialInvalidate");
RecyclerView.this.eatRequestLayout();
RecyclerView.this.mAdapterHelper.preProcess();
if(!RecyclerView.this.mLayoutRequestEaten) {
RecyclerView.this.rebindUpdatedViewHolders();
}
RecyclerView.this.resumeRequestLayout(true);
TraceCompat.endSection();
}
}
}
};
dans le dispatchLayout (), nous pouvons trouver qu'il y a une erreur dans it:
void dispatchLayout() {
if(this.mAdapter == null) {
Log.e("RecyclerView", "No adapter attached; skipping layout");
} else if(this.mLayout == null) {
Log.e("RecyclerView", "No layout manager attached; skipping layout");
} else {
j'ai ce problème , quelques temps un problème recycleView mettre dans le ScrollView objet
Après vérification de la mise en œuvre, la raison semble être la suivante. Si RecyclerView est mis dans un ScrollView, alors pendant la mesure step sa hauteur n'est pas spécifiée (parce que ScrollView permet n'importe quelle hauteur) et, en conséquence, obtient égale à la hauteur minimale (selon la mise en œuvre) qui est apparemment zéro.
vous avez un couple de options de fixation:
- fixer une certaine hauteur à RecyclerView
- Mettez ScrollView.fillViewport to true
- ou garder RecyclerView à l'extérieur de ScrollView. À mon avis, c'est la meilleure option, et de loin. Si la hauteur de RecyclerView n'est pas limitée - ce qui est le cas quand il est mis dans ScrollView - alors toutes les vues de L'Adaptateur ont assez de place verticalement et sont créées en même temps. Il n'y a plus de vue recyclage ce qui va à l'encontre du but de RecyclerView .
(peut être suivi pour android.support.v4.widget.NestedScrollView
ainsi)
1) Créer des ViewHolder qui ne fait rien :)
// SampleHolder.java
public class SampleHolder extends RecyclerView.ViewHolder {
public SampleHolder(View itemView) {
super(itemView);
}
}
2) Encore une fois créer RecyclerView qui ne fait rien:)
// SampleRecycler.java
public class SampleRecycler extends RecyclerView.Adapter<SampleHolder> {
@Override
public SampleHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return null;
}
@Override
public void onBindViewHolder(SampleHolder holder, int position) {
}
@Override
public int getItemCount() {
return 0;
}
}
3) Maintenant, lorsque votre vrai recycleur n'est pas prêt, il suffit d'utiliser l'échantillon comme ci-dessous.
RecyclerView myRecycler = (RecyclerView) findViewById(R.id.recycler_id);
myRecycler.setLayoutManager(new LinearLayoutManager(this));
myRecycler.setAdapter(new SampleRecycler());
Ce n'est pas la meilleure solution, mais il fonctionne bien! Espérer cette fonction est utile.
cela se produit lorsque vous ne paramétrez pas l'adaptateur pendant la phase de création:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
....
}
public void onResume() {
super.onResume();
mRecyclerView.setAdapter(mAdapter);
....
}
déplacez simplement le réglage de l'adaptateur dans onCreate avec des données vides et quand vous avez l'appel de données:
mAdapter.notifyDataSetChanged();
j'ai eu la même erreur que je l'ai corrigée en faisant cela si vous attendez des données comme moi en utilisant retrofit ou quelque chose comme ça
Mis de l'avant Oncreate
private ArtistArrayAdapter adapter;
private RecyclerView recyclerView;
mettez - les dans votre Oncreate
recyclerView = (RecyclerView) findViewById(R.id.cardList);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new ArtistArrayAdapter( artists , R.layout.list_item ,getApplicationContext());
recyclerView.setAdapter(adapter);
quand vous recevez des données mettez
adapter = new ArtistArrayAdapter( artists , R.layout.list_item ,getApplicationContext());
recyclerView.setAdapter(adapter);
maintenant allez dans votre classe ArtistArrayAdapter et faites ceci ce qu'elle fera est si votre tableau est vide ou est null elle fera GetItemCount return 0 si non, c'est la taille d'artistes tableau
@Override
public int getItemCount() {
int a ;
if(artists != null && !artists.isEmpty()) {
a = artists.size();
}
else {
a = 0;
}
return a;
}
ces lignes doivent être dans OnCreate
:
mmAdapter = new Adapter(msgList);
mrecyclerView.setAdapter(mmAdapter);
ArtistArrayAdapter adapter = new ArtistArrayAdapter(this, artists);
recyclerView = (RecyclerView) findViewById(R.id.cardList);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
il suffit de remplacer le code ci-dessus par ceci et cela devrait fonctionner. Ce que vous avez fait de mal, c'est que vous avez appelé setAdapter(adaptateur) avant d'appeler layout manager.
C'est vraiment une simple erreur que vous obtenez, il n'a pas besoin de faire des codes dans cette. cette erreur est due au mauvais fichier de mise en page utilisé par l'activité. Par IDE j'ai créé automatiquement un layout v21 d'un layout qui est devenu un layout par défaut de l'activité. tous les codes que je faisais dans l'ancien fichier de mise en page et le nouveau n'avaient que peu de codes xml, ce qui a mené à cette erreur.
Solution: copier tous les codes de l'ancienne disposition et coller dans la mise en page v 21
dans mon cas, j'installais l'adaptateur à l'intérieur de onLocationChanged()
et je déboguais l'émulateur. Comme il n'a pas détecté de changement d'emplacement, il n'a pas tiré. Lorsque je les réglais manuellement dans les commandes étendues de l'émulateur, cela fonctionnait comme prévu.
j'ai résolu cette erreur. Vous avez juste besoin d'ajouter layout manager et ajouter le vide de l'adaptateur.
comme CE code:
myRecyclerView.setLayoutManager(...//your layout manager);
myRecyclerView.setAdapter(new RecyclerView.Adapter() {
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return null;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
}
@Override
public int getItemCount() {
return 0;
}
});
//other code's
// and for change you can use if(mrecyclerview.getadapter != speacialadapter){
//replice your adapter
//}
cela se produit parce que la mise en page gonflée réelle est différente de celle qui est référée par vous tout en trouvant le recyclerView. Par défaut, lorsque vous créez le fragment, la méthode onCreateView apparaît comme suit::
return inflater.inflate(R.layout.<related layout>,container.false);
au lieu de cela, créer séparément la vue et l'utiliser pour faire référence à recyclerView
View view= inflater.inflate(R.layout.<related layout>,container.false);
recyclerview=view.findViewById(R.id.<recyclerView ID>);
return view;
initialiser D'abord l'adaptateur
public void initializeComments(){
comments = new ArrayList<>();
comments_myRecyclerView = (RecyclerView) findViewById(R.id.comments_recycler);
comments_mLayoutManager = new LinearLayoutManager(myContext);
comments_myRecyclerView.setLayoutManager(comments_mLayoutManager);
updateComments();
getCommentsData();
}
public void updateComments(){
comments_mAdapter = new CommentsAdapter(comments, myContext);
comments_myRecyclerView.setAdapter(comments_mAdapter);
}
Lorsqu'il y a un changement dans l'ensemble de données, il suffit d'appeler la méthode updateComments.
dans ma situation, il s'agissait d'un composant oublié qui se situe dans la classe des visualiseurs mais qui n'était pas situé dans le fichier de mise en page
j'ai eu le même problème et j'ai réalisé que je réglais à la fois le LayoutManage r et adaptateur après avoir récupéré les données de ma source au lieu de mettre les deux dans la méthode onCreate .
salesAdapter = new SalesAdapter(this,ordersList);
salesView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
salesView.setAdapter(salesAdapter);
a alors informé l'adaptateur sur le changement de données
//get the Orders
Orders orders;
JSONArray ordersArray = jObj.getJSONArray("orders");
for (int i = 0; i < ordersArray.length() ; i++) {
JSONObject orderItem = ordersArray.getJSONObject(i);
//populate the Order model
orders = new Orders(
orderItem.getString("order_id"),
orderItem.getString("customer"),
orderItem.getString("date_added"),
orderItem.getString("total"));
ordersList.add(i,orders);
salesAdapter.notifyDataSetChanged();
}
ce numéro s'explique par le fait que vous n'ajoutez pas de LayoutManager
à votre RecyclerView
.
une autre raison est que vous appelez ce code dans un NonUIThread. Assurez-vous d'appeler cet appel dans le UIThread.
la solution est seulement vous devez ajouter un LayoutManager
pour le RecyclerView
avant vous setAdapter
dans le fil UI.
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mon problème était mon point de vue de recycleur ressemblait à ceci
<android.support.v7.widget.RecyclerView
android:id="@+id/chatview"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
</android.support.v7.widget.RecyclerView>
quand il aurait dû ressembler à ceci
<android.support.v7.widget.RecyclerView
android:id="@+id/chatview"
android:layout_width="395dp"
android:layout_height="525dp"
android:layout_marginTop="52dp"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="8dp"></android.support.v7.widget.RecyclerView>
</android.support.constraint.ConstraintLayout>
dans votre classe d'adaptateur RecyclerView
, par exemple MyRecyclerViewAdapter
, faites un constructeur avec les params suivants.
MyRecyclerViewAdapter(Context context, List<String> data) {
this.mInflater = LayoutInflater.from(context); // <-- This is the line most people include me miss
this.mData = data;
}
mData
sont les données que vous transmettez à l'adaptateur. Il est en option si vous n'avez pas de données à transmettre.
mInflater
est l'objet LayoutInflater
que vous avez créé et que vous utilisez dans la fonction OnCreateViewHolder
de l'adaptateur.
après cela, vous attachez l'adaptateur dans la MainActivity ou où vous voulez sur le fil principal / UI correctement comme
MyRecyclerViewAdapter recyclerAdapter;
OurDataStuff mData;
....
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Like this:
RecyclerView recyclerView = findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerAdapter = new RecyclerAdapter(this, mData); //this, is the context. mData is the data you want to pass if you have any
recyclerView.setAdapter(recyclerAdapter);
}
....
Résolu en positionnant la liste vide initialisée et l'adaptateur en bas et en appelant notifydatase changed lorsque les résultats sont trouvés.
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
recyclerviewItems.setLayoutManager(linearLayoutManager);
someAdapter = new SomeAdapter(getContext(),feedList);
recyclerviewItems.setAdapter(someAdapter);
j'ai perdu 16 minutes de ma vie avec ce numéro, donc je vais juste admettre à cette erreur incroyablement embarrassante que je faisais - j'utilise le couteau de beurre et je lie la vue dans onCreateView dans ce fragment.
il a fallu beaucoup de temps pour comprendre pourquoi je n'avais pas de gestionnaire de LAYOUT - mais évidemment les vues sont injectées de sorte qu'elles ne seront pas réellement nulles, de sorte que le recycleur ne sera jamais null .. oups!
@BindView(R.id.recycler_view)
RecyclerView recyclerView;
@Override
public View onCreateView(......) {
View v = ...;
ButterKnife.bind(this, v);
setUpRecycler()
}
public void setUpRecycler(Data data)
if (recyclerView == null) {
/*very silly because this will never happen*/
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
//more setup
//...
}
recyclerView.setAdapter(new XAdapter(data));
}
si vous avez un problème comme cette trace votre vue et utiliser quelque chose comme uiautomatorviewer
pour ceux qui utilisent le RecyclerView
dans un fragment et le gonfler à partir d'autres vues: en gonflant l'ensemble de la vue fragment, assurez-vous que vous liez le RecyclerView
à sa vue racine.
je me connectais et je faisais tout pour l'adaptateur correctement, mais je n'ai jamais fait la reliure. Cette réponse par @Prateek Agarwal a tout pour moi, Mais voici plus d'élaboration.
Kotlin
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val rootView = inflater?.inflate(R.layout.fragment_layout, container, false)
recyclerView = rootView?.findViewById(R.id.recycler_view_id)
// rest of my stuff
recyclerView?.setHasFixedSize(true)
recyclerView?.layoutManager = viewManager
recyclerView?.adapter = viewAdapter
// return the root view
return rootView
}
Java
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView= inflater.inflate(R.layout.fragment_layout,container.false);
recyclerview= rootView.findViewById(R.id.recycler_view_id);
// rest ...
return rootView;
}
ce n'est pas vraiment une réponse, mais j'avais le même problème, même si le code était correct. Parfois, c'est la plus simple des marques. Dans ce cas, l'erreur de L'OP peut aussi être manquante <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
du Manifeste, qui reproduit la même erreur.