简体   繁体   English

即使我调用 notifyDataSetChanged(),RecyclerView 也不显示项目

[英]RecyclerView don't show items even if I call notifyDataSetChanged()

I'm using a RecyclerView to show datas but even if I call notifyDataSetChanged() after I got the list from Room db I can't see the items on the first creation of the fragment, but only on second one.我正在使用 RecyclerView 来显示数据,但即使我在从 Room db 获得列表后调用notifyDataSetChanged() ,我也看不到第一次创建片段时的项目,而只能看到第二个片段。

MainActivity.class MainActivity.class

package it.bastoner.taboom;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.MenuItem;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.room.Room;

import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.navigation.NavigationBarView;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import it.bastoner.taboom.database.CardDAO;
import it.bastoner.taboom.database.CardEntity;
import it.bastoner.taboom.database.DatabaseTaboom;
import it.bastoner.taboom.fragments.AddFragment;
import it.bastoner.taboom.fragments.BaseCardFragment;
import it.bastoner.taboom.fragments.PlayFragment;
import it.bastoner.taboom.fragments.UpdateFragment;

public class MainActivity extends AppCompatActivity {

private static final String TAG = "MainActivity";
private List<CardEntity> cardList;
private boolean cardListIsUpdated;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Log.d(TAG, ">>MainActivity created");

    cardList = new ArrayList<CardEntity>();

    // Setting bottomNavigation
    BottomNavigationView bottomNav = findViewById(R.id.bottom_nav);
    bottomNav.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {

        //TODO ANIMATION

        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {

            // By using switch we can easily get the selected fragment by using there id.
            Fragment selectedFragment = null;
            switch (item.getItemId()) {
                case R.id.add_nav:
                    selectedFragment = new AddFragment(cardList);
                    break;
                case R.id.play_nav:
                    selectedFragment = new PlayFragment(cardList);
                    break;
                case R.id.update_nav:
                    selectedFragment = new UpdateFragment(cardList);
                    break;
            }
            // It will help to replace the
            // one fragment to other.
            getSupportFragmentManager()
                    .beginTransaction()
                    .replace(R.id.fragment_container, selectedFragment)
                    .commit();
            return true;
        }

    });

    // As soon as the application opens the play fragment should be shown to the user
    bottomNav.setSelectedItemId(R.id.play_nav);

    loadCardList();

}

private void loadCardList() {

    CardDAO cardDAO = DatabaseTaboom.getDatabase(getApplicationContext()).cardDao();

    // Setting cardsList
    ExecutorService executor = Executors.newSingleThreadExecutor();

    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            cardList = cardDAO.getAll();
            Log.d(TAG, ">>Cardlist: " + cardList);
            BaseCardFragment actualFragment = (BaseCardFragment) getSelectedFragment();
            if (actualFragment != null)
                actualFragment.updateUI();
            else
                Log.d(TAG, ">>Null fragment");
        }
    };

    executor.execute(runnable);

}

private Fragment getSelectedFragment() {

    FragmentManager fragmentManager = getSupportFragmentManager();
    List<Fragment> fragmentList = fragmentManager.getFragments();
    for (Fragment f: fragmentList) {
        if (f != null && f.isVisible())
            return f;
    }
    return null;
}

}

PlayFragment.class播放片段.class

package it.bastoner.taboom.fragments;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.media.MediaPlayer;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.PagerSnapHelper;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SnapHelper;

import android.os.CountDownTimer;
import android.text.InputFilter;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.util.List;
import java.util.Locale;

import it.bastoner.taboom.R;
import it.bastoner.taboom.adapter.RecyclerViewAdapter;
import it.bastoner.taboom.database.CardEntity;
import it.bastoner.taboom.filters.MinMaxFilter;
import it.bastoner.taboom.listeners.MyDialogListener;


public class PlayFragment extends BaseCardFragment implements MyDialogListener {

    private static final String TAG = "PlayFragment";

    private RecyclerView recyclerView;

    private TextView timerTextView;
    private Button playPauseButton;
    private Button resetButton;
    private CountDownTimer countDownTimer;
    private long startTimeInMillis;
    private boolean timerIsRunning;
    private long timeLeftInMillis = startTimeInMillis;

    private MediaPlayer endTimerSound;

    public PlayFragment(List<CardEntity> cardList) {
        super(cardList);
        //Log.d(TAG, "PlayFragment created");
    }

    @Override
    public void updateUI() {
        recyclerView.getAdapter().notifyDataSetChanged();
        Log.d(TAG, ">>Update, number of items: " + recyclerView.getAdapter().getItemCount());
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        Log.d(TAG, ">>OnCreateView");
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_play, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        Log.d(TAG, ">>OnViewCreated");

        setRecyclerView();

        setTimerSound();

        setTimer();

        setDialogModifyTimer();

        updateUI();

    }

   // other methods...

}

As you can see in the console正如您在控制台中看到的安慰 the cardList has received elements before the call of UpdateUI() but in update the first time is called no elements are seen. cardList在调用UpdateUI()之前已接收到元素,但在第一次调用 update 时没有看到任何元素。 Can you help me?你能帮助我吗? I don't understand why, thank you.我不明白为什么,谢谢。

I think you need to set the Data in the RecyclerAdapter.我认为您需要在 RecyclerAdapter 中设置数据。 Then call it inside your fragment with a ViewModel.然后使用 ViewModel 在您的片段中调用它。 I'm using Kotlin sorry.我正在使用 Kotlin 抱歉。 This works only if u are using RoomDB with viewModel and repositories仅当您将 RoomDB 与 viewModel 和存储库一起使用时才有效

In your RecyclerAdapter, you first need to set an empty list在您的 RecyclerAdapter 中,您首先需要设置一个空列表


private var timerList = emptyList<EntityClassName>()
    
    // Now use a method to set the Data
    fun setData(timer : List<EntityClassName>){
        this.timerList = timer
        notifyDataSetChanged()
    }

Then you call this on your Fragment inside OnViewCreated.然后在 OnViewCreated 中的 Fragment 上调用它。

sharedViewModel.readAllData.observe(viewLifecycleOwner,Observer {
            data -> myAdapter.setData(data)}) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM