Подтвердить что ты не робот

Поддержка RecyclerView не показывает ничего, пока не коснется

Я использую поддержку RecyclerView в своем приложении, и я вижу самую причудливую вещь. Он не отображает никаких элементов, пока я не коснусь прокрутки. Затем, внезапно, RecyclerView заполняет себя. Я проверил, что список, поддерживающий адаптер, заселен, и что onCreatViewHolder и onBindViewHolder никогда не вызываются до события касания.

Вот как я настроил recyclerview:

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        Drawable divider = new ColorDrawable(ProfileInfo.getCurrentProfileColor());
        mInboxList.addItemDecoration(new DividerItemDecoration(getActivity(), divider, false));
        mInboxList.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
        mInboxList.setAdapter(new InboxAdapter(getActivity(), new ArrayList<Conversation>()));
        new AsyncTask<Void, Void, List<Conversation>{

              public List<Conversation> doInBackground(...){
                   //load the conversations
                   return conversations;
              }

              public void onPostExecute(List<Conversation> conversations){
                   ((InboxAdapter) mInboxList.getAdapter()).clear(false);
                   ((InboxAdapter) mInboxList.getAdapter()).addAll(conversations);

              }

        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
     }

Вот суть моего адаптера:

public class InboxAdapter extends RecyclerView.Adapter<InboxAdapter.ViewHolder> {
    List<Conversation> mConversations; //initialized in contructor

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = mInflater.inflate(R.layout.inbox_item, parent, false);
        ViewHolder holder = new ViewHolder(v);
        Log.d(LOG_TAG, "oncreateviewholder : " + viewType); //never called when I first bind the adapter
        return holder;
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
        final Conversation item = mConversations.get(position);
        Log.d(LOG_TAG, "binding " + position);
        ...
    }

    @Override
    public int getItemCount() {
        Log.d(LOG_TAG, "item count: " + mConversations.size());
        return mConversations.size();
    }

    /**
     * Empties out the whole and optionally notifies
     */
    public void clear(boolean notify) {
        mConversations.clear();
        if (notify) {
            notifyDataSetChanged();
        }
    }

    public void addAll(List<Conversation> conversations) {
        mConversations.addAll(conversations);
        notifyDataSetChanged();
    }


}

Здесь файл макета:

<?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"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:paddingTop="?attr/actionBarSize">


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

Я использую recyclerview-v7: 21.0.3, работающий на Moto X с версией 4.4.4.

EDIT: Гладкая прокрутка в конце onPostExecute, похоже, устраняет проблему:

if (mInboxList.getAdapter().getItemCount() > 0) {
    mInboxList.smoothScrollToPosition(0);
}
4b9b3361

Ответ 1

Если у кого-то еще есть эта проблема с использованием RxJava и Retrofit, я решил эту проблему, добавив оператор .observeOn(AndroidSchedulers.mainThread()) в мою цепочку методов перед подпиской. Я читал, что по умолчанию он позаботился и, следовательно, явно не нужен, но, я думаю, нет. Надеюсь, это поможет.

Пример:

public void loadPhotos() {
    mTestPhotoService.mServiceAPI.getPhotos()
                                 .subscribeOn(Schedulers.io())
                                 .observeOn(AndroidSchedulers.mainThread())
                                 .subscribe(photoList -> mRecyclerActivity.OnPhotosLoaded(photoList));
}

Ответ 2

В моем случае только это сработало:

recyclerView.smoothScrollToPosition(arrayModel.size-1); // I am passing last position here you can pass any existing position

RecyclerView показывал данные только тогда, когда я их прокручивал. Поэтому вместо пользовательской прокрутки вручную я добавил строку выше, которая будет прокручивать программный просмотр recyclerView.

Ответ 3

я также страдаю от той же самой проблемы в течение 2 дней, теперь это сделано после добавления этой линии.

adaptor.notifyDataSetChanged()//после адаптера уведомления добавьте этот mRecyclerView.smoothScrollToPosition(list.size-1)

Ответ 4

В моем случае это произошло только на Android 6. Над этой версией у меня не было никаких проблем. Итак, что я нашел для работы, это использовать recyclerView.scrollBy(0, 0). Проверьте это, может быть, это будет работать для вас тоже.

Ответ 5

Итак, сначала, как и все остальные, я только что добавил:

recyclerView.smoothScrollToPosition(0)

и это сработало довольно хорошо, однако это было нехорошо, и вам приходилось не забывать добавлять его каждый раз. а затем я последовал за комментарием @SudoPlz и отвечу на другой вопрос, и это тоже сработало, вы должны расширить RecyclerView и переопределить requestLayout:

private boolean mRequestedLayout = false;

@SuppressLint("WrongCall")
@Override
public void requestLayout() {
    super.requestLayout();
    // We need to intercept this method because if we don't our children will never update
    // Check https://stackoverflow.com/questions/49371866/recyclerview-wont-update-child-until-i-scroll
    if (!mRequestedLayout) {
        mRequestedLayout = true;
        this.post(() -> {
            mRequestedLayout = false;
            layout(getLeft(), getTop(), getRight(), getBottom());
            onLayout(false, getLeft(), getTop(), getRight(), getBottom());
        });
    }
}

пока я бы предпочел, чтобы это было исправлено через 4, 5 года, однако это был хороший обходной путь, и вы не забудете о них, по вашему мнению.

Ответ 6

Вам нужно будет запустить материал, который вы делаете в onPostExecute, в потоке пользовательского интерфейса, чтобы RecyclerView перерисовывался. Вот почему работает гладкая прокрутка, потому что она работает в потоке пользовательского интерфейса и, следовательно, вызывает перерисовку представления.

Ответ 7

Это, скорее всего, потому, что вы не вызываете правильные методы уведомления RecyclerView.Adapter. Для этого у вас гораздо более гранулярный интерфейс, чем в ListAdapters. Например, в addAll() вы должны вызвать notifyItemRangeInserted(oldConversationsSize, conversations.size()) вместо notifyDataSetChanged