feat: Added history (RecyclerView) and fixed bugs

This commit is contained in:
SunZar 2025-02-20 10:53:37 +03:00
parent 8f683c1f0c
commit 04b26f8eaf
9 changed files with 206 additions and 95 deletions

View File

@ -63,12 +63,12 @@ public class UserRepositoryImpl implements UserRepository, SignUserRepository {
ArrayList<HistoryEntity> result1 = new ArrayList<>(historiesDto.size()); ArrayList<HistoryEntity> result1 = new ArrayList<>(historiesDto.size());
for (HistoryDto history : historiesDto) { for (HistoryDto history : historiesDto) {
final Integer id1 = history.id; final Integer id1 = history.id;
final Integer idUser = history.idUser; final String username1 = history.username;
final Long time = history.time; final Long time = history.time;
final String nameReader = history.nameReader;
final String type = history.type; final String type = history.type;
if (idUser != null && id1 != null){ final Integer code = history.code;
result1.add(new HistoryEntity(id1, idUser, time, nameReader, type)); if (username1 != null && id1 != null){
result1.add(new HistoryEntity(id1, username1, time, type, code));
} }
} }
return result1; return result1;

View File

@ -10,21 +10,19 @@ public class HistoryDto {
public Integer id; public Integer id;
@Nullable @Nullable
@SerializedName("idUser") @SerializedName("username")
public Integer idUser; public String username;
@Nullable @Nullable
@SerializedName("time") @SerializedName("time")
public Long time; public Long time;
@Nullable
@SerializedName("nameReader")
public String nameReader;
@Nullable @Nullable
@SerializedName("type") @SerializedName("type")
public String type; public String type;
@Nullable
@SerializedName("code")
public Integer code;
} }

View File

@ -19,12 +19,12 @@ public class HistoryEntity {
} }
@Nullable @Nullable
public Integer getIdUser() { public String getUsername() {
return idUser; return username;
} }
public void setIdUser(@Nullable Integer idUser) { public void setUsername(@Nullable String username) {
this.idUser = idUser; this.username = username;
} }
@Nullable @Nullable
@ -36,15 +36,6 @@ public class HistoryEntity {
this.time = time; this.time = time;
} }
@Nullable
public String getNameReader() {
return nameReader;
}
public void setNameReader(@Nullable String nameReader) {
this.nameReader = nameReader;
}
@Nullable @Nullable
public String getType() { public String getType() {
return type; return type;
@ -54,28 +45,37 @@ public class HistoryEntity {
this.type = type; this.type = type;
} }
public HistoryEntity(@Nullable Integer id, @Nullable Integer idUser, @Nullable Long time, @Nullable String nameReader, @Nullable String type) { @Nullable
public Integer getCode() {
return code;
}
public void setCode(@Nullable Integer code) {
this.code = code;
}
public HistoryEntity(@Nullable Integer id, @Nullable String username, @Nullable Long time, @Nullable String type, @Nullable Integer code) {
this.id = id; this.id = id;
this.idUser = idUser; this.username = username;
this.time = time; this.time = time;
this.nameReader = nameReader;
this.type = type; this.type = type;
this.code = code;
} }
@Nullable @Nullable
@SerializedName("idUser") @SerializedName("username")
public Integer idUser; public String username;
@Nullable @Nullable
@SerializedName("time") @SerializedName("time")
public Long time; public Long time;
@Nullable
@SerializedName("nameReader")
public String nameReader;
@Nullable @Nullable
@SerializedName("type") @SerializedName("type")
public String type; public String type;
@Nullable
@SerializedName("code")
public Integer code;
} }

View File

@ -11,11 +11,12 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import ru.myitschool.work.databinding.ItemHistoryBinding; import ru.myitschool.work.databinding.ItemHistoryBinding;
import ru.myitschool.work.domain.entities.HistoryEntity;
import ru.myitschool.work.ui.History; import ru.myitschool.work.ui.History;
public class HistoryAdapter extends RecyclerView.Adapter<HistoryAdapter.ViewHolder> { public class HistoryAdapter extends RecyclerView.Adapter<HistoryAdapter.ViewHolder> {
private final List<History> data = new ArrayList<>(); private final List<HistoryEntity> data = new ArrayList<>();
@NonNull @NonNull
@Override @Override
@ -40,7 +41,7 @@ public class HistoryAdapter extends RecyclerView.Adapter<HistoryAdapter.ViewHold
return data.size(); return data.size();
} }
public void updateData(List<History> newData) { public void updateData(List<HistoryEntity> newData) {
data.clear(); data.clear();
data.addAll(newData); data.addAll(newData);
notifyDataSetChanged(); notifyDataSetChanged();
@ -54,11 +55,11 @@ public class HistoryAdapter extends RecyclerView.Adapter<HistoryAdapter.ViewHold
binding = ItemHistoryBinding.bind(itemView); binding = ItemHistoryBinding.bind(itemView);
} }
public void bind(History item) { public void bind(HistoryEntity item) {
binding.time.setText(item.getTime().toString().substring(0, 10) + " " binding.time.setText(item.getTime().toString().substring(0, 10) + " "
+ item.getTime().toString().substring(11, 16)); + item.getTime().toString().substring(11, 16));
binding.nameReader.setText(item.getNameReader()); binding.nameReader.setText(item.getNameReader());
if (item.getPassageType() == 1){ if (item.getType() == 1){
binding.type.setText("QR-code"); binding.type.setText("QR-code");
} }
else{ else{

View File

@ -6,15 +6,19 @@ import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.Navigation; import androidx.navigation.Navigation;
import com.squareup.picasso.Picasso; import com.squareup.picasso.Picasso;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
@ -23,16 +27,23 @@ import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory; import retrofit2.converter.gson.GsonConverterFactory;
import ru.myitschool.work.R; import ru.myitschool.work.R;
import ru.myitschool.work.databinding.FragmentInformationBinding; import ru.myitschool.work.databinding.FragmentInformationBinding;
import ru.myitschool.work.domain.entities.HistoryEntity;
import ru.myitschool.work.domain.entities.UserEntity;
import ru.myitschool.work.utils.Constants; import ru.myitschool.work.utils.Constants;
import ru.myitschool.work.ui.History; import ru.myitschool.work.ui.History;
import ru.myitschool.work.ui.StoreAPI; import ru.myitschool.work.ui.StoreAPI;
import ru.myitschool.work.ui.User; import ru.myitschool.work.ui.User;
import ru.myitschool.work.ui.qr.scan.QrScanDestination; import ru.myitschool.work.ui.qr.scan.QrScanDestination;
import ru.myitschool.work.utils.PreferenceManager;
import ru.myitschool.work.utils.Utils;
public class InformationFragment extends Fragment { public class InformationFragment extends Fragment {
FragmentInformationBinding binding; FragmentInformationBinding binding;
SharedPreferences sharedPreferences; PreferenceManager preferenceManager;
ArrayList<History> history = new ArrayList<>(); InformationViewModel viewModel;
List<HistoryEntity> history = new ArrayList<>();
private boolean loadingHistory;
private String username;
@Nullable @Nullable
@Override @Override
@ -45,9 +56,11 @@ public class InformationFragment extends Fragment {
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
sharedPreferences = getContext().getSharedPreferences(getString(R.string.app_name), Context.MODE_PRIVATE); //sharedPreferences = getContext().getSharedPreferences(getString(R.string.app_name), Context.MODE_PRIVATE);
preferenceManager = new PreferenceManager(this.getContext());
getInformation(); username = preferenceManager.getString(Constants.KEY_USER_USERNAME);
viewModel = new ViewModelProvider(this).get(InformationViewModel.class);
//getInformation();
binding.scan.setOnClickListener(view1 -> { binding.scan.setOnClickListener(view1 -> {
onClickScan(view); onClickScan(view);
@ -58,12 +71,13 @@ public class InformationFragment extends Fragment {
}); });
binding.refreshLayout.setOnRefreshListener(() -> { binding.refreshLayout.setOnRefreshListener(() -> {
onClickRefresh(); viewModel.load();
}); });
//TODO: SERVER ZAGRUZKA LISTAAAAAAAAAAAAAAA //TODO: SERVER ZAGRUZKA LISTAAAAAAAAAAAAAAA
HistoryAdapter adapter = new HistoryAdapter(); HistoryAdapter adapter = new HistoryAdapter();
binding.historylist.setAdapter(adapter); binding.historylist.setAdapter(adapter);
adapter.updateData(history);
subscribe(viewModel, adapter, view);
//getParentFragmentManager() //getParentFragmentManager()
requireActivity().getSupportFragmentManager().setFragmentResultListener(QrScanDestination.REQUEST_KEY, getViewLifecycleOwner(), (requestKey, result) -> { requireActivity().getSupportFragmentManager().setFragmentResultListener(QrScanDestination.REQUEST_KEY, getViewLifecycleOwner(), (requestKey, result) -> {
@ -79,11 +93,14 @@ public class InformationFragment extends Fragment {
Navigation.findNavController(view).navigate(R.id.action_informationFragment_to_resultFragment); Navigation.findNavController(view).navigate(R.id.action_informationFragment_to_resultFragment);
//getFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, resFragment).commit(); //getFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, resFragment).commit();
}); });
viewModel.changeSelectedUsername(username);
viewModel.load();
} }
private void onClickRefresh() { /*private void onClickRefresh() {
getInformation(); getInformation();
} }*/
private void onClickScan(View view) { private void onClickScan(View view) {
Navigation.findNavController(view).navigate(R.id.action_informationFragment_to_qrScanFragment); Navigation.findNavController(view).navigate(R.id.action_informationFragment_to_qrScanFragment);
@ -91,11 +108,101 @@ public class InformationFragment extends Fragment {
} }
private void onClickLogout(View view) { private void onClickLogout(View view) {
sharedPreferences.edit().clear().apply(); preferenceManager.clear();
Navigation.findNavController(view).navigate(R.id.action_informationFragment_to_loginFragment); Navigation.findNavController(view).navigate(R.id.action_informationFragment_to_loginFragment);
//getFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, new LoginFragment()).commit(); //getFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, new LoginFragment()).commit();
} }
private void subscribe(final InformationViewModel viewModel, final HistoryAdapter historyAdapter, View view) {
viewModel.stateAllUserHistoryLiveData.observe(getViewLifecycleOwner(), state -> {
loadingHistory = state.isLoading();
//Toast.makeText(this.getContext(), "Zashol", Toast.LENGTH_SHORT).show();
binding.loading.setVisibility(Utils.visibleOrGone(loadingHistory));
if (state.isLoading() == false) {
if (state.getItemsHistory() != null) {
history = state.getItemsHistory();
//TODO: BINDING
//binding.address.setText(history.getAddress());
//binding.countVolunteers.setText("Количество волонтёров: " + history.getUsers().size());
//List<ItemUserEntity> itemUserEntities = new ArrayList<>();
//for (FullUserEntity el : volunteerCenter.getUsers()) {
// UserEntity user = new ItemUserEntity(el.getId(), el.getLastName(), el.getFirstName());
// itemUserEntities.add(user);
//}
historyAdapter.updateData(history);
historyAdapter.notifyDataSetChanged();
binding.refreshLayout.setRefreshing(false);
}
} else {
Toast.makeText(this.getContext(), "Error", Toast.LENGTH_SHORT).show();
takeError();
}
binding.refreshLayout.setRefreshing(false);
});
/*
viewModel.stateHistoryLiveData.observe(getViewLifecycleOwner(), state -> {
loadingHistory = state.isLoading();
//Toast.makeText(this.getContext(), "vse", Toast.LENGTH_SHORT).show();
binding.loading.setVisibility(Utils.visibleOrGone(loadingHistory));
if (state.isLoading() == false) {
if (state.getItemsHistory() != null) {
volunteerCenters = state.getItemsVolunteerCenters();
List<String> volunteerCentersString = new ArrayList<String>();
for (ItemVolunteerCenterEntity el : volunteerCenters) {
volunteerCentersString.add(el.getAddress());
}
ArrayAdapter<String> spinnerAdapter;
spinnerAdapter = new ArrayAdapter<String>(this.getContext(), android.R.layout.simple_spinner_item, volunteerCentersString);
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
binding.spinner.setAdapter(spinnerAdapter);
//binding.spinner.setPromptId(R.string.chooseday);
//binding.spinner.setSelection(1, true);
String volunteerCenterId = preferenceManager.getString(Constants.KEY_VOLUNTEER_CENTER_ID);
if (volunteerCenterId != null) {
//Toast.makeText(this.getContext(), volunteerCenterId, Toast.LENGTH_SHORT).show();
binding.spinner.setSelection(Integer.parseInt(volunteerCenterId) - 1, true);
}
} else {
Toast.makeText(this.getContext(), "Error", Toast.LENGTH_SHORT).show();
}
}
/*boolean isSuccess = !state.isLoading()
&& state.getErrorMessage() == null
&& state.getItems() != null;
//binding.refresh.setEnabled(!state.isLoading());
//if (!state.isLoading()) //binding.refresh.setRefreshing(false);
binding.recycler.setVisibility(Utils.visibleOrGone(isSuccess));
binding.error.setVisibility(Utils.visibleOrGone(state.getErrorMessage() != null));
binding.loading.setVisibility(Utils.visibleOrGone(state.isLoading()));
binding.error.setText(state.getErrorMessage());
if (isSuccess) {
listAdapter.updateData(state.getItems());
}
});
*/
}
/*private void getInformation() { /*private void getInformation() {
Retrofit retrofit = new Retrofit.Builder() Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ru.myitschool.work.core.Constants.SERVER_ADDRESS) .baseUrl(ru.myitschool.work.core.Constants.SERVER_ADDRESS)

View File

@ -12,23 +12,17 @@ import java.util.List;
import ru.myitschool.work.data.UserRepositoryImpl; import ru.myitschool.work.data.UserRepositoryImpl;
import ru.myitschool.work.domain.GetAllUserHistoryUseCase; import ru.myitschool.work.domain.GetAllUserHistoryUseCase;
import ru.myitschool.work.domain.sign.IsUserExistUseCase; import ru.myitschool.work.domain.entities.HistoryEntity;
import ru.sicampus.bootcamp2025.data.UserRepositoryImpl; import ru.myitschool.work.domain.entities.Status;
import ru.sicampus.bootcamp2025.domain.GetUsersListUseCase;
import ru.sicampus.bootcamp2025.domain.GetVolunteerCenterByIdUseCase;
import ru.sicampus.bootcamp2025.domain.GetVolunteerCentersListUseCase;
import ru.sicampus.bootcamp2025.domain.entites.FullVolunteerCenterEntity;
import ru.sicampus.bootcamp2025.domain.entites.ItemVolunteerCenterEntity;
import ru.sicampus.bootcamp2025.domain.entites.Status;
public class InformationViewModel extends ViewModel { public class InformationViewModel extends ViewModel {
private final MutableLiveData<State> mutableStateCentersLiveData = new MutableLiveData<>(); private final MutableLiveData<State> mutableStateHistoryLiveData = new MutableLiveData<>();
public final LiveData<State> stateCentersLiveData = mutableStateCentersLiveData; public final LiveData<State> stateHistoryLiveData = mutableStateHistoryLiveData;
private final MutableLiveData<State> mutableStateVolunteerCenterLiveData = new MutableLiveData<>(); private final MutableLiveData<State> mutableStateAllUserHistoryLiveData = new MutableLiveData<>();
public final LiveData<State> stateVolunteerCenterLiveData = mutableStateVolunteerCenterLiveData; public final LiveData<State> stateAllUserHistoryLiveData = mutableStateAllUserHistoryLiveData;
public final GetAllUserHistoryUseCase getAllUserHistoryUseCase = new GetAllUserHistoryUseCase( public final GetAllUserHistoryUseCase getAllUserHistoryUseCase = new GetAllUserHistoryUseCase(
UserRepositoryImpl.getInstance() UserRepositoryImpl.getInstance()
@ -38,26 +32,26 @@ public class InformationViewModel extends ViewModel {
update(); update();
}*/ }*/
private Integer volunteerCenterId; private String username;
public void changeSelectedVCId(@NonNull Integer volunteerCenterId) { public void changeSelectedUsername(@NonNull String username) {
this.volunteerCenterId = volunteerCenterId; this.username = this.username;
} }
public void load() { public void load() {
mutableStateCentersLiveData.setValue(new ListViewModel.State(null, null, null, true)); mutableStateAllUserHistoryLiveData.setValue(new InformationViewModel.State(null, null, false));
getAllUserHistoryUseCase.execute(status -> { getHistById(username);
mutableStateCentersLiveData.postValue(fromStatus(status)); /*getAllUserHistoryUseCase.execute(username, status -> {
}); mutableStateHistoryLiveData.postValue(fromStatus(status));
});*/
} }
public void getVCById() { public void getHistById() {
getVolunteerCenterByIdUseCase.execute(volunteerCenterId, status -> { getAllUserHistoryUseCase.execute(username, status -> {
Log.d("taggis", status.getStatusCode() + " " + status.getErrors()); //Log.d("taggis", status.getStatusCode() + " " + status.getErrors());
if (status.getStatusCode() == 200 && status.getErrors() == null) { if (status.getStatusCode() == 200 && status.getErrors() == null) {
mutableStateVolunteerCenterLiveData.postValue(new ListViewModel.State( mutableStateAllUserHistoryLiveData.postValue(new InformationViewModel.State(
status.getErrors() != null ? status.getErrors().getLocalizedMessage() : null, status.getErrors() != null ? status.getErrors().getLocalizedMessage() : null,
null,
status.getValue(), status.getValue(),
false false
)); ));
@ -67,11 +61,10 @@ public class InformationViewModel extends ViewModel {
}); });
} }
private ListViewModel.State fromStatus(Status<List<ItemVolunteerCenterEntity>> status) { private InformationViewModel.State fromStatus(Status<List<HistoryEntity>> status) {
return new ListViewModel.State( return new InformationViewModel.State(
status.getErrors() != null ? status.getErrors().getLocalizedMessage() : null, status.getErrors() != null ? status.getErrors().getLocalizedMessage() : null,
status.getValue(), status.getValue(),
null,
false false
); );
} }
@ -81,17 +74,13 @@ public class InformationViewModel extends ViewModel {
private final String errorMessage; private final String errorMessage;
@Nullable @Nullable
private final List<ItemVolunteerCenterEntity> itemsVolunteerCenters; private final List<HistoryEntity> itemsHistory;
@Nullable
private final FullVolunteerCenterEntity volunteerCenter;
private final boolean isLoading; private final boolean isLoading;
public State(@Nullable String errorMessage, @Nullable List<ItemVolunteerCenterEntity> itemsVolunteerCenters, FullVolunteerCenterEntity volunteerCenter, boolean isLoading) { public State(@Nullable String errorMessage, @Nullable List<HistoryEntity> itemsHistory, boolean isLoading) {
this.errorMessage = errorMessage; this.errorMessage = errorMessage;
this.itemsVolunteerCenters = itemsVolunteerCenters; this.itemsHistory = itemsHistory;
this.volunteerCenter = volunteerCenter;
this.isLoading = isLoading; this.isLoading = isLoading;
} }
@ -101,13 +90,8 @@ public class InformationViewModel extends ViewModel {
} }
@Nullable @Nullable
public List<ItemVolunteerCenterEntity> getItemsVolunteerCenters() { public List<HistoryEntity> getItemsHistory() {
return itemsVolunteerCenters; return itemsHistory;
}
@Nullable
public FullVolunteerCenterEntity getVolunteerCenter() {
return volunteerCenter;
} }
public boolean isLoading() { public boolean isLoading() {

View File

@ -13,6 +13,7 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.setFragmentResult import androidx.fragment.app.setFragmentResult
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.Navigation.findNavController
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import com.google.mlkit.vision.barcode.BarcodeScanner import com.google.mlkit.vision.barcode.BarcodeScanner
import com.google.mlkit.vision.barcode.BarcodeScannerOptions import com.google.mlkit.vision.barcode.BarcodeScannerOptions
@ -40,7 +41,7 @@ class QrScanFragment : Fragment(R.layout.fragment_qr_scan) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
_binding = FragmentQrScanBinding.bind(view) _binding = FragmentQrScanBinding.bind(view)
sendResult(bundleOf()) sendResult(bundleOf())
subscribe() subscribe(view)
initCallback() initCallback()
} }
@ -48,7 +49,7 @@ class QrScanFragment : Fragment(R.layout.fragment_qr_scan) {
binding.close.setOnClickListener { viewModel.close() } binding.close.setOnClickListener { viewModel.close() }
} }
private fun subscribe() { private fun subscribe(view: View) {
viewModel.state.collectWhenStarted(this) { state -> viewModel.state.collectWhenStarted(this) { state ->
binding.loading.visibleOrGone(state is QrScanViewModel.State.Loading) binding.loading.visibleOrGone(state is QrScanViewModel.State.Loading)
binding.viewFinder.visibleOrGone(state is QrScanViewModel.State.Scan) binding.viewFinder.visibleOrGone(state is QrScanViewModel.State.Scan)
@ -62,11 +63,11 @@ class QrScanFragment : Fragment(R.layout.fragment_qr_scan) {
when (action) { when (action) {
is QrScanViewModel.Action.RequestPermission -> requestPermission(action.permission) is QrScanViewModel.Action.RequestPermission -> requestPermission(action.permission)
is QrScanViewModel.Action.CloseWithCancel -> { is QrScanViewModel.Action.CloseWithCancel -> {
goBack() goBack(view)
} }
is QrScanViewModel.Action.CloseWithResult -> { is QrScanViewModel.Action.CloseWithResult -> {
sendResult(QrScanDestination.packToBundle(action.result)) sendResult(QrScanDestination.packToBundle(action.result))
goBack() goBack(view)
} }
} }
} }
@ -113,9 +114,10 @@ class QrScanFragment : Fragment(R.layout.fragment_qr_scan) {
super.onDestroyView() super.onDestroyView()
} }
private fun goBack() { private fun goBack(view: View) {
findNavControllerOrNull()?.popBackStack() findNavController(view).navigate<Any>(R.id.action_qrScanFragment_to_informationFragment)
?: requireActivity().onBackPressedDispatcher.onBackPressed() /*findNavControllerOrNull()?.popBackStack()
?: requireActivity().onBackPressedDispatcher.onBackPressed()*/
} }
private fun sendResult(bundle: Bundle) { private fun sendResult(bundle: Bundle) {

View File

@ -0,0 +1,9 @@
package ru.myitschool.work.utils;
import android.view.View;
public class Utils {
public static int visibleOrGone(boolean isVisible) {
return isVisible ? View.VISIBLE : View.GONE;
}
}

View File

@ -86,6 +86,16 @@
android:layout_gravity="center" android:layout_gravity="center"
/> />
<ProgressBar
android:id="@+id/loading"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>