SQLite数据库变更后RecyclerView无法自动更新UI的问题求助
SQLite数据库变更后RecyclerView无法自动更新UI的问题求助
我现在在做一个安卓应用,其中有个Fragment需要展示某场赛事任务里的可用人员,原本期望数据库新增或删除人员时UI能自动同步更新,但目前只有Fragment刚创建时才会加载显示人员列表,后续数据库有任何增删操作,UI完全没反应。我不想改用Room,打算继续用原生SQLite来实现,下面是我的相关代码,求各位帮忙看看问题出在哪,怎么修改才能实现自动更新?
我的TeamViewModel代码
public class TeamViewModel extends AndroidViewModel { private static final String TAG = "TeamViewModel"; private TeamRepository teamRepository; private MutableLiveData<PlayerTeam> playersLiveData; public TeamViewModel(Application application) { super(application); Log.d(TAG, "Initializing TeamViewModel"); // Initialize repository and LiveData teamRepository = new TeamRepository(new DatabaseHelper(application)); playersLiveData = new MutableLiveData<>(); Log.d(TAG, "TeamViewModel initialized successfully"); } public LiveData<PlayerTeam> getPlayersForMatch(int matchId) { Log.d(TAG, "getPlayersForMatch called with matchId: " + matchId); // Fetch players from the repository in a background thread new Thread(() -> { try { Log.d(TAG, "Fetching players from repository for matchId: " + matchId); PlayerTeam playerTeam = teamRepository.getPlayersForMatch(matchId); if (playerTeam == null) { Log.e(TAG, "PlayerTeam fetched is null for matchId: " + matchId); } else { Log.d(TAG, "PlayerTeam fetched successfully for matchId: " + matchId); Log.d(TAG, "Team 1 Players Count: " + playerTeam.getTeam1Players().size()); for (Player player : playerTeam.getTeam1Players()) { Log.d(TAG, "Team 1 Player: " + player.toString()); } Log.d(TAG, "Team 2 Players Count: " + playerTeam.getTeam2Players().size()); for (Player player : playerTeam.getTeam2Players()) { Log.d(TAG, "Team 2 Player: " + player.toString()); } } // Post the fetched data to LiveData playersLiveData.postValue(playerTeam); } catch (Exception e) { Log.e(TAG, "Error while fetching players for matchId: " + matchId, e); } }).start(); Log.d(TAG, "Returning playersLiveData for matchId: " + matchId); return playersLiveData; } }
我的PlayerAdapter代码
public class PlayerAdapter extends RecyclerView.Adapter<PlayerAdapter.PlayerViewHolder> { private List<Player> players; // Constructor to accept List<Player> public PlayerAdapter(List<Player> players) { this.players = players; } @NonNull @Override public PlayerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.item_player, parent, false); return new PlayerViewHolder(view); } @Override public void onBindViewHolder(@NonNull PlayerViewHolder holder, int position) { Player player = players.get(position); holder.bind(player); } @Override public int getItemCount() { return players != null ? players.size() : 0; } // Method to update the dataset and notify the RecyclerView public void updatePlayers(List<Player> newPlayers) { DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffUtil.Callback() { @Override public int getOldListSize() { return players != null ? players.size() : 0; } @Override public int getNewListSize() { return newPlayers != null ? newPlayers.size() : 0; } @Override public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { // Assuming Player has a unique identifier like ID return players.get(oldItemPosition).getPlayerId() == newPlayers.get(newItemPosition).getPlayerId(); } @Override public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { // Compare content equality return players.get(oldItemPosition).equals(newPlayers.get(newItemPosition)); } }); // Update the dataset this.players = newPlayers; // Notify RecyclerView of changes diffResult.dispatchUpdatesTo(this); } // ViewHolder class public static class PlayerViewHolder extends RecyclerView.ViewHolder { private TextView playerName; public PlayerViewHolder(@NonNull View itemView) { super(itemView); playerName = itemView.findViewById(R.id.playerNameView); } public void bind(Player player) { playerName.setText(player.getName()); } } }
我的Fragment代码
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Log.d(TAG, "onCreateView called"); // Inflate the layout for the fragment View view = inflater.inflate(R.layout.activity_mp_teams, container, false); Log.d(TAG, "Layout inflated successfully"); // SharedPreferences for team names if (getActivity() != null) { sharedPreferences = requireContext().getSharedPreferences("match_prefs", Context.MODE_PRIVATE); } // Initialize RecyclerViews and TextViews for team names team1RecyclerView = view.findViewById(R.id.team1PlayerRecyclerView); team2RecyclerView = view.findViewById(R.id.team2PlayerRecyclerView); TextView teamATextView = view.findViewById(R.id.team1TextView); TextView teamBTextView = view.findViewById(R.id.team2TextView); // Set team names in TextViews from SharedPreferences String teamAName = sharedPreferences.getString("teamAName", ""); String teamBName = sharedPreferences.getString("teamBName", ""); teamATextView.setText(teamAName); teamBTextView.setText(teamBName); // Set GridLayoutManager for RecyclerViews (4 columns per team) team1RecyclerView.setLayoutManager(new GridLayoutManager(getContext(), 4)); team2RecyclerView.setLayoutManager(new GridLayoutManager(getContext(), 4)); // Initialize adapters with empty lists team1Adapter = new PlayerAdapter(new ArrayList<>()); team2Adapter = new PlayerAdapter(new ArrayList<>()); // Set adapters to RecyclerViews team1RecyclerView.setAdapter(team1Adapter); team2RecyclerView.setAdapter(team2Adapter); // Initialize ViewModel teamViewModel = new ViewModelProvider(this).get(TeamViewModel.class); Log.d(TAG, "onCreateView completed"); return view; } @Override public void onResume() { super.onResume(); Log.d(TAG, "onResume called"); matchId = sharedPreferences.getLong("currentMatchId", -1); teamViewModel.getPlayersForMatch((int) matchId).observe(getViewLifecycleOwner(), playerTeam -> { Log.d(TAG, "LiveData observed, updating UI"); if (playerTeam != null) { List<Player> team1Players = playerTeam.getTeam1Players(); List<Player> team2Players = playerTeam.getTeam2Players(); Log.d(TAG, "Team 1 Players Count: " + team1Players.size()); for (Player player : team1Players) { Log.d(TAG, "Team 1 Player: " + player.toString()); } // Update Team 1 Adapter team1Adapter.updatePlayers(team1Players); Log.d(TAG, "Team 2 Players Count: " + team2Players.size()); for (Player player : team2Players) { Log.d(TAG, "Team 2 Player: " + player.toString()); } team2Adapter.updatePlayers(team2Players); } else { Log.e(TAG, "PlayerTeam object is null"); } }); Log.d(TAG, "onResume completed"); } }
我自己分析的问题(可能不对)
现在的代码里,LiveData只在getPlayersForMatch被调用时才会去查一次数据库,但是数据库变了之后,完全没有通知LiveData去重新查询的机制,因为原生SQLite不像Room自带了数据变更监听。所以现在只是单次查询,不是持续监听。
求各位大佬帮忙给出具体的修改方案,让数据库增删人员后,UI能自动刷新!
备注:内容来源于stack exchange,提问作者Reddy
相关产品推荐
相关产品推荐

