Отображение индикатора активности с помощью RxSwift и MVVM

Мой ответ основан на коде, предоставленном Ником. Этот код измеряет общее количество байтов, которые заняты сериализованным объектом. Таким образом, это фактически измеряет размер сериализации 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: пример изменен для поддержки вычисления размера памяти объектов массива.

1
задан pankaj 16 January 2019 в 08:44
поделиться

1 ответ

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)
0
ответ дан Farshad jahanmanesh 16 January 2019 в 08:44
поделиться