#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.