从 mvvm 获取的数据在第一次访问时不会在回收站视图中更新
Posted
技术标签:
【中文标题】从 mvvm 获取的数据在第一次访问时不会在回收站视图中更新【英文标题】:Fetched data from mvvm is not updated in recycler view on first visit 【发布时间】:2020-12-19 13:19:33 【问题描述】:PreAdmissionList.java
public class PreAdmissionList extends Fragment implements View.OnClickListener, AdapterApprovalList.OnItemClickListener
private BasicInfoViewModel basicInfoViewModel;
private AdapterApprovalList adapterApprovalList;
private RecyclerView rvApprovalList;
public PreAdmissionList()
// Required empty public constructor
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_pre_admission_list, container, false);
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
super.onViewCreated(view, savedInstanceState);
view.findViewById(R.id.fab_add_new_admission).setOnClickListener(this);
rvApprovalList = view.findViewById(R.id.rv_approval_list);
basicInfoViewModel = new ViewModelProvider(requireActivity()).get(BasicInfoViewModel.class);
basicInfoViewModel.init();
basicInfoViewModel.getApprovalList().observe(getViewLifecycleOwner(), new Observer<List<ModelBasicInfo>>()
@Override
public void onChanged(List<ModelBasicInfo> modelBasicInfos)
adapterApprovalList.notifyDataSetChanged();
);
initRecyclerView();
private void initRecyclerView()
adapterApprovalList = new AdapterApprovalList(this,basicInfoViewModel.getApprovalList().getValue());
rvApprovalList.setHasFixedSize(true);
rvApprovalList.setLayoutManager(new LinearLayoutManager(getContext()));
rvApprovalList.setAdapter(adapterApprovalList);
AdapterApprovalList.java
public class AdapterApprovalList extends RecyclerView.Adapter<AdapterApprovalList.ALViewHolder>
private Context context;
private OnItemClickListener onItemClickListener;
private List<ModelBasicInfo> modelBasicInfoList;
public AdapterApprovalList(OnItemClickListener onItemClickListener,List<ModelBasicInfo> modelBasicInfoList)
this.onItemClickListener = onItemClickListener;
this.modelBasicInfoList=modelBasicInfoList;
@NonNull
@Override
public ALViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
context = parent.getContext();
View view = LayoutInflater.from(context).inflate(R.layout.template_approval_list_item,parent,false);
return new ALViewHolder(view,onItemClickListener);
@Override
public void onBindViewHolder(@NonNull ALViewHolder holder, int position)
ModelBasicInfo basicInfo = modelBasicInfoList.get(position);
StringBuilder fullName = new StringBuilder();
fullName.append(basicInfo.getFirstName()).append(" ");
fullName.append(basicInfo.getMiddleName()).append(" ");
fullName.append(basicInfo.getLastName()).append(" ");
holder.fullName.setText(fullName);
holder.id.setText("RKC00"+String.valueOf(basicInfo.getId()));
@Override
public int getItemCount()
return modelBasicInfoList.size();
static class ALViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
OnItemClickListener mOnItemClickListener;
TextView fullName,id;
public ALViewHolder(@NonNull View itemView,OnItemClickListener mOnItemClickListener)
super(itemView);
this.mOnItemClickListener = mOnItemClickListener;
fullName = itemView.findViewById(R.id.tv_text_full_name);
id = itemView.findViewById(R.id.tv_text_approval_id);
itemView.setOnClickListener(this);
@Override
public void onClick(View v)
mOnItemClickListener.onApprovalItemClick(getAbsoluteAdapterPosition());
public interface OnItemClickListener
void onApprovalItemClick(int position);
BasicInfoViewModel.java
public class BasicInfoViewModel extends ViewModel
private BasicInfoRepo basicInfoRepo;
private MutableLiveData<List<ModelBasicInfo>> approvalList;
public void init()
if(approvalList != null)
return;
basicInfoRepo = BasicInfoRepo.getInstance();
approvalList = basicInfoRepo.getApprovalList();
public LiveData<List<ModelBasicInfo>> getApprovalList()
return approvalList;
public void insertBasicInfo(ModelBasicInfo modelBasicInfo)
basicInfoRepo.insertData(modelBasicInfo);
public void updateApprovalStatus(int id)
basicInfoRepo.updateStatus(id);
BasicInfoRepo.java
public class BasicInfoRepo
private static BasicInfoRepo instance;
static ConnectionClass connectionClass = new ConnectionClass();
private List<ModelBasicInfo> approvalList = new ArrayList<>();
public static BasicInfoRepo getInstance()
if(instance== null)
instance = new BasicInfoRepo();
return instance;
public MutableLiveData<List<ModelBasicInfo>> getApprovalList()
loadApprovalList();
MutableLiveData<List<ModelBasicInfo>> mList = new MutableLiveData<>();
mList.setValue(approvalList);
return mList;
private void loadApprovalList()
LoadApprovalList loadApprovalList = new LoadApprovalList();
loadApprovalList.execute();
public void insertData(ModelBasicInfo modelBasicInfo)
InsertBasicInfo insertBasicInfo = new InsertBasicInfo();
insertBasicInfo.execute(modelBasicInfo);
public void updateStatus(int id)
UpdateBasicInfo updateBasicInfo = new UpdateBasicInfo();
updateBasicInfo.execute(id);
private static class InsertBasicInfo extends AsyncTask<ModelBasicInfo,Integer,String>
@Override
protected void onPreExecute()
super.onPreExecute();
@Override
protected String doInBackground(ModelBasicInfo... model)
String result = null;
// Log.i("Testing db",lists[0].get(0).getFirstName());
try
Connection connection = connectionClass.CONN();
if(connection==null)
result = "Error in connection !!!";
else
//Date object
Date date= new Date();
//getTime() returns current time in milliseconds
long time = date.getTime();
//Passed the milliseconds to constructor of Timestamp class
Timestamp ts = new Timestamp(time);
PreparedStatement ps = connection.prepareStatement("insert into PreAdmissionDetails values(?,?,?,?,?,?,?,?,?,?)");
ps.setString(1,model[0].getFirstName());
ps.setString(2,model[0].getMiddleName());
ps.setString(3,model[0].getLastName());
ps.setString(4,model[0].getMotherName());
ps.setDate(5, java.sql.Date.valueOf(model[0].getDateOfBirth()));
ps.setString(6,model[0].getMobileNo());
ps.setInt(7,0);
ps.setInt(8,0);
ps.setBoolean(9,false);
ps.setTimestamp(10, ts);
ps.executeUpdate();
result = "Submitted Successfully !!!";
catch (Exception ex)
Log.e("sqlerror",ex.toString());
result=ex.getMessage();
Log.e("sqlerror","result : "+result);
return result;
@Override
protected void onPostExecute(String s)
super.onPostExecute(s);
private static class UpdateBasicInfo extends AsyncTask<Integer,Integer,String>
@Override
protected String doInBackground(Integer... integers)
String result = null;
try
Connection connection = connectionClass.CONN();
if(connection==null)
result = "Error in connection !!!";
else
PreparedStatement ps = connection.prepareStatement("UPDATE PreAdmissionDetails SET STATUS=? WHERE id=?");
ps.setInt(1,0);
ps.setInt(2,integers[0]);
ps.executeUpdate();
result = "Updated Successfully !!!";
catch (Exception ex)
Log.e("sqlerror",ex.toString());
result=ex.getMessage();
Log.e("sqlerror","result : "+result.toString());
return result;
private class LoadApprovalList extends AsyncTask<Void,Void,Void>
@Override
protected Void doInBackground(Void... voids)
String result = null;
try
Connection connection = connectionClass.CONN();
if(connection==null)
result = "Error in connection !!!";
else
PreparedStatement ps = connection.prepareStatement("select * from preadmissiondetails");
ResultSet rs = ps.executeQuery();
approvalList.clear();
while (rs.next())
approvalList.add(new ModelBasicInfo(rs.getInt(1),
rs.getString(2),
rs.getString(3),
rs.getString(4),
rs.getString(5),
rs.getString(6),
rs.getString(7),
rs.getInt(8),
rs.getInt(9),
rs.getBoolean(10)));
result = "Fetched Successfully !!!";
catch (Exception ex)
Log.e("sqlerror",ex.toString());
result=ex.getMessage();
Log.e("sqlerror","result : "+result.toString());
return null;
问题就在这里,当我打开应用程序时,回收站视图中没有项目,我认为可能是互联网速度较慢,它会在一段时间后获取数据,但不显示数据。但是当我导航到其他一些片段并返回预录取列表时,它会显示数据。
【问题讨论】:
【参考方案1】:你的问题在这里:
public MutableLiveData<List<ModelBasicInfo>> getApprovalList()
loadApprovalList();
MutableLiveData<List<ModelBasicInfo>> mList = new MutableLiveData<>();
mList.setValue(approvalList);
return mList;
loadApprovalList()
启动一个 AsyncTask,这是一个异步操作(换句话说,产生结果需要时间)。 getApprovalList()
方法不只是停在那里等待loadApprovalList()
完成。它继续并在第一次执行时返回一个空列表。但是到第二次执行时,approvalList
现在有了一个值,因为 AsyncTask 已经完成。所以它在第二次执行时返回正确的数据。当您返回 Fragment 时,它会再次执行,因为您的 ViewModel 中的 init
块此时正在执行第二次。
解决方案是将approvalList
设为 LiveData。这样,当 AsyncTask 更新approvalList 时,您的ViewModel 可以观察到变化。您的 ViewModel 应该在您的 Repository 中观察 approvalList
,就像您的 Fragment 如何在您的 ViewModel 中观察 getApprovalList()
方法一样。
【讨论】:
以上是关于从 mvvm 获取的数据在第一次访问时不会在回收站视图中更新的主要内容,如果未能解决你的问题,请参考以下文章
如何在MVVM架构中观察RecyclerView适配器中的LiveData?
无法使用MVVM通过Xceed CheckListBox获取SelectedItems