Мой ответ основан на коде, предоставленном Ником. Этот код измеряет общее количество байтов, которые заняты сериализованным объектом. Таким образом, это фактически измеряет размер сериализации stuff + plain object memory (просто сериализуйте, например, int
, и вы увидите, что общее количество сериализованных байтов не 4
). Поэтому, если вы хотите получить необработанный байтовый номер, используемый именно для вашего объекта, вам нужно немного изменить этот код. Например:
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class ObjectSizeCalculator {
private Object getFirstObjectReference(Object o) {
String objectType = o.getClass().getTypeName();
if (objectType.substring(objectType.length()-2).equals("[]")) {
try {
if (objectType.equals("java.lang.Object[]"))
return ((Object[])o)[0];
else if (objectType.equals("int[]"))
return ((int[])o)[0];
else
throw new RuntimeException("Not Implemented !");
} catch (IndexOutOfBoundsException e) {
return null;
}
}
return o;
}
public int getObjectSizeInBytes(Object o) {
final String STRING_JAVA_TYPE_NAME = "java.lang.String";
if (o == null)
return 0;
String objectType = o.getClass().getTypeName();
boolean isArray = objectType.substring(objectType.length()-2).equals("[]");
Object objRef = getFirstObjectReference(o);
if (objRef != null && !(objRef instanceof Serializable))
throw new RuntimeException("Object must be serializable for measuring it's memory footprint using this method !");
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.close();
byte[] bytes = baos.toByteArray();
for (int i = bytes.length - 1, j = 0; i != 0; i--, j++) {
if (objectType != STRING_JAVA_TYPE_NAME) {
if (bytes[i] == 112)
if (isArray)
return j - 4;
else
return j;
} else {
if (bytes[i] == 0)
return j - 1;
}
}
} catch (Exception e) {
return -1;
}
return -1;
}
}
Я тестировал это решение с примитивными типами, String и некоторыми тривиальными классами. Также могут быть и не рассмотренные случаи.
UPDATE: пример изменен для поддержки вычисления размера памяти объектов массива.
ViewModel должен обрабатывать показ или скрытие IndicatorView (если есть одно загрузочное представление), поскольку ваше представление должно быть тупым, используйте BehaviorRelay вместо переменной (переменная запрещена)
в viewModel
// create a subject and set the starter state, every time your viewModel
// needs to show or hide a loading, just send an event
let showLoading = BehaviorRelay<Bool>(value: true)
// your async function
func getManufacturerList() -> Observable {
// notify subscriber to show the indicator view
showLoading.accept(true)
// do some works
// notify subscribers to hide the indicator view
showLoading.accept(false)
}
и в вашем контроллере вида
// bind your indicator view to that subject and wait for events
showLoading.asObservable().observeOn(MainScheduler.instance).bind(to: indicatorView.rx.isHidden).disposed(by: disposeBag)