You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android添加数据后RecyclerView无法实时更新列表问题求助

Room数据库新增数据后RecyclerView无法实时更新

我是Android开发新手,项目使用TabLayout、ViewPager2、Fragment和底部导航栏,做了两个Fragment:Tab1负责输入数据,Tab2用RecyclerView展示数据,数据存储依赖Room数据库。目前遇到的问题是:输入数据后Toast提示已成功存入数据库,但RecyclerView里看不到新数据,必须重启应用才能显示更新。

相关代码

WriteFragment(输入数据页面)

View mView;
EditText addTitle;
EditText addContent;
ImageButton btnSave;

public WriteFragment() {

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    mView = inflater.inflate(R.layout.fragment_write, container, false);

    addTitle = mView.findViewById(R.id.edt_add_title);
    addContent = mView.findViewById(R.id.edt_add_content);
    btnSave = mView.findViewById(R.id.btn_save);
    btnSave.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) { addItems(); }
    });

    hideSoftKeyboard();
    return mView;
}

private void addItems() {
    String strTitle = addTitle.getText().toString().trim();
    String strContent = addContent.getText().toString().trim();

    if (TextUtils.isEmpty(strTitle)|| TextUtils.isEmpty(strContent)){
        return;
    }
    ItemsObject itemsObject = new ItemsObject(strTitle,strContent);
    MainActivity.diaryDatabase.getInstance(getActivity()).userDAO().insert(itemsObject);
    Toast.makeText(getActivity(),"Successfully Added",Toast.LENGTH_SHORT).show();

    addTitle.setText("");
    addContent.setText("");
    hideSoftKeyboard();
}

public void hideSoftKeyboard() {
    try {
        InputMethodManager inputMethodManager = (InputMethodManager)
                getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE);
        inputMethodManager.hideSoftInputFromWindow(getActivity().getCurrentFocus().getWindowToken(), 0);
    } catch (NullPointerException exception) {
        exception.printStackTrace();
    }
}

DiaryLogFragment(数据展示页面)

package com.haki.mysimplehakidiarynotes.fragments.diary_tabs;

import android.os.Bundle;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.haki.mysimplehakidiarynotes.ItemsAdapter;
import com.haki.mysimplehakidiarynotes.ItemsObject;
import com.haki.mysimplehakidiarynotes.MainActivity;
import com.haki.mysimplehakidiarynotes.R;
import java.util.ArrayList;
import java.util.List;

public class DiaryLogFragment extends Fragment {
    View mView;
    private RecyclerView rcvItems;
    private ItemsAdapter itemsAdapter;
    private List<ItemsObject> itemsObjectList;

    public DiaryLogFragment(){ }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        mView = inflater.inflate(R.layout.fragment_diary_log, container, false);

        rcvItems = mView.findViewById(R.id.rcv_items);
        itemsAdapter = new ItemsAdapter();

        itemsObjectList = DiaryDatabase.getInstance(getActivity()).userDAO().getListUser();
        itemsAdapter.setData(itemsObjectList);

        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
        rcvItems.setLayoutManager(linearLayoutManager);
        rcvItems.setFocusable(true);
        rcvItems.setAdapter(itemsAdapter);

        return mView;
    }
}

ItemsAdapter(RecyclerView适配器)

package com.haki.mysimplehakidiarynotes;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.ramotion.foldingcell.FoldingCell;
import java.util.List;

public class ItemsAdapter extends RecyclerView.Adapter<ItemsAdapter.ItemViewHolder>{
    private List<ItemsObject> mListItems;

    public void setData(List<ItemsObject> list) {
        this.mListItems = list;
        notifyDataSetChanged();
    }

    @NonNull
    @Override
    public ItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.layout_items, parent, false);
        return new ItemViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ItemViewHolder holder, int position) {
        ItemsObject itemsObject = mListItems.get(position);
        if (itemsObject == null){
            return;
        }
        holder.txtTitle.setText(itemsObject.getTitle());
        holder.txtContent.setText(itemsObject.getContent());

        holder.foldingCell.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                holder.foldingCell.toggle(false);
            }
        });
    }

    @Override
    public int getItemCount() {
        if (mListItems != null){
            return mListItems.size();
        }
        return 0;
    }

    public class ItemViewHolder extends RecyclerView.ViewHolder {
        FoldingCell foldingCell;
        TextView txtTitle;
        TextView txtContent;

        public ItemViewHolder(@NonNull View itemView) {
            super(itemView);
            foldingCell = itemView.findViewById(R.id.folding_cell);
            txtTitle = itemView.findViewById(R.id.tv_title);
            txtContent = itemView.findViewById(R.id.tv_content);
        }
    }
}

问题原因

  1. DiaryLogFragment仅在创建时读取一次数据:它只在onCreateView里执行了一次数据库查询,之后数据库数据更新时,没有重新获取数据并通知适配器刷新。
  2. Room普通查询无监听能力:当前DAO的getListUser()是单次查询,不会主动告知应用数据已变化。

解决方法

方法一:用Room+LiveData实现自动监听(官方推荐)

LiveData是Jetpack组件,能自动感知生命周期,数据变化时自动通知UI更新,步骤如下:

  1. 修改DAO接口,将查询方法返回类型改为LiveData<List<ItemsObject>>:
@Dao
public interface UserDAO {
    @Insert
    void insert(ItemsObject itemsObject);

    // 改为返回LiveData
    @Query("SELECT * FROM items_table")
    LiveData<List<ItemsObject>> getListUser();
}
  1. 修改DiaryLogFragment,观察LiveData的变化:
public class DiaryLogFragment extends Fragment {
    View mView;
    private RecyclerView rcvItems;
    private ItemsAdapter itemsAdapter;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mView = inflater.inflate(R.layout.fragment_diary_log, container, false);

        rcvItems = mView.findViewById(R.id.rcv_items);
        itemsAdapter = new ItemsAdapter();

        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
        rcvItems.setLayoutManager(linearLayoutManager);
        rcvItems.setFocusable(true);
        rcvItems.setAdapter(itemsAdapter);

        // 观察LiveData,数据变化时自动更新Adapter
        DiaryDatabase.getInstance(getActivity()).userDAO().getListUser()
                .observe(getViewLifecycleOwner(), itemsObjects -> {
                    itemsAdapter.setData(itemsObjects);
                });

        return mView;
    }
}

这样,当数据库里新增数据时,LiveData会自动把新列表推送给Fragment,Adapter就会刷新显示新数据。

方法二:手动通知数据更新(适合简单场景)

如果暂时不想用LiveData,可以在保存数据后手动触发DiaryLogFragment刷新:

  1. 在MainActivity定义通信接口:
public interface OnDataUpdatedListener {
    void onDataUpdated();
}
  1. 让DiaryLogFragment实现接口:
public class DiaryLogFragment extends Fragment implements OnDataUpdatedListener {
    // ... 原有代码 ...

    @Override
    public void onDataUpdated() {
        // 重新查询数据库并更新Adapter
        List<ItemsObject> newList = DiaryDatabase.getInstance(getActivity()).userDAO().getListUser();
        itemsAdapter.setData(newList);
    }

    // ... 原有代码 ...
}
  1. 在WriteFragment保存数据后调用接口:
private void addItems() {
    // ... 原有代码 ...
    MainActivity.diaryDatabase.getInstance(getActivity()).userDAO().insert(itemsObject);
    Toast.makeText(getActivity(),"Successfully Added",Toast.LENGTH_SHORT).show();

    // 通知数据更新
    if (getActivity() instanceof OnDataUpdatedListener) {
        ((OnDataUpdatedListener) getActivity()).onDataUpdated();
    }

    // ... 原有代码 ...
}

注意:方法二需要处理Fragment不在前台的情况(比如用户在Tab1保存数据后没切到Tab2),而方法一的LiveData会自动处理,更稳定。


内容的提问来源于stack exchange,提问作者ThankYouCamOnGraciasXieXie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 03:55:16