I want to show a list of information about devices. First, I call API to get a list of devices. After that, in onResponse function, I for each device and call another API to get data of each device. But this data is not updated in View. View just show a list of device, can not show data of each device. I think that observe don't catch event when updating data of devices
My Device class:
public class Device {
@SerializedName("Altitude")
private Double altitude;
@SerializedName("Latitude")
private Double latitude;
@SerializedName("Longtitude")
private Double longitude;
@SerializedName("NodeId")
private String nodeId;
@SerializedName("ReverseGeocode")
private String reverseGeocode;
@SerializedName("Title")
private Integer title;
@Expose
private List<Data> data = new ArrayList<>();
}
My repository:
public class DeviceRepository {
DeviceApi deviceApi;
MutableLiveData<List<Device>> mutableLiveData = new MutableLiveData<>();
//some code to init...
//get devices
public MutableLiveData<List<Device>> getDevices() {
final List<Device> devices = new ArrayList<>();
Call<List<Device>> call = deviceApi.getDevices();
call.enqueue(new Callback<List<Device>>() {
@Override
public void onResponse(Call<List<Device>> call, Response<List<Device>> response) {
if(response.body() != null) {
for (Device device: response.body()) {
devices.add(device);
}
mutableLiveData.setValue(devices);
//set data for device by call API
for(int i = 0; i<mutableLiveData.getValue().size(); i++){
DeviceRepository.this.getDataOfDevice(mutableLiveData.getValue().get(i));
}
}
}
@Override
public void onFailure(Call<List<Device>> call, Throwable t) {
}
});
return mutableLiveData;
}
//call API to get Data
public void getDataOfDevice(Device device) {
final List<Data> data = new ArrayList<>();
Call<List<Data>> call = deviceApi.getDataByNodeId(device.getNodeId());
call.enqueue(new Callback<List<Data>>() {
@Override
public void onResponse(Call<List<Data>> call, Response<List<Data>> response) {
if(response.body() != null && response.body().size()>0) {
data.add(response.body().get(0));
device.setData(data);
}
}
@Override
public void onFailure(Call<List<Data>> call, Throwable t) {
System.out.println("fail");
}
});
}
}
This is my ViewModel:
public class DeviceViewModel extends ViewModel {
private MutableLiveData<List<Device>> devices;
private DeviceRepository deviceRepository = new DeviceRepository();
public MutableLiveData<List<Device>> getDevices() {
devices = deviceRepository.getDevices();
return devices;
}
}
This is Fragment:
public class DeviceFragment extends Fragment{
private DeviceViewModel deviceViewModel;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
DeviceFragmentBinding binding = DataBindingUtil.inflate(inflater, R.layout.device_fragment, container, false);
binding.setLifecycleOwner(this);
View root = inflater.inflate(R.layout.device_fragment, container, false);
deviceViewModel = new ViewModelProvider(this).get(DeviceViewModel.class);
final ListView listView = root.findViewById(R.id.list);
deviceViewModel.getDevices().observe(getViewLifecycleOwner(), devices -> {
final List<String> list = new ArrayList<>();
for (Device device: devices) {
String info = device.getData().size() > 0 ? device.getData().get(0).getTime().toString() : "no data";
list.add(device.getNodeId() + "-"+info);
}
ArrayAdapter<String> itemsAdapter =
new ArrayAdapter<String>(getContext(), android.R.layout.simple_list_item_1, list);
listView.setAdapter(itemsAdapter);
});
return root;
}
}
And device_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<layout>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.Device.DeviceFragment">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/list">
</ListView>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>