Данные, полученные из mvvm, не обновляются в режиме рециркуляции при первом посещении

#android #android-recyclerview #android-asynctask #android-viewmodel #android-mvvm

#Android #android-recyclerview #android-asynctask #android-viewmodel #android-mvvm

Вопрос:

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 resu<
        }


        @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 resu<

        }
    }

    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 завершен. Таким образом, он возвращает правильные данные при втором выполнении. Он выполняется во второй раз, когда вы возвращаетесь к своему фрагменту, потому что init блок в вашей ViewModel выполняется во второй раз в этот момент.

Решение заключается в создании approvalList LiveData. Таким образом, когда AsyncTask обновляет approvalList, ваша ViewModel может наблюдать изменения. Ваша ViewModel должна наблюдать approvalList в вашем репозитории, точно так же, как ваш фрагмент наблюдает за getApprovalList() методом в вашей ViewModel.