Android Виджет во фрагменте, получая исключение IllegalStateException в Rx-подписке - PullRequest
0 голосов
/ 13 февраля 2020

У меня есть пара исключений IllegalStateExceptions, которые иногда возникают из-за того, что this.progressContainer имеет значение null. В целом это кажется невозможным, но я беспокоюсь, что делаю ложное предположение о том, как работают эти события жизненного цикла. Я чувствую, что в этом случае нет необходимости делать эту защитную проверку, поскольку это должно быть гарантировано на onActivityCreated. Здесь определенно есть некоторая краткость, которую я не показываю, поэтому, если это не достаточно полная картина, чтобы объяснить возникшую у меня проблему, пожалуйста, прокомментируйте, и я дополню эту картину дальше.

В целом в viewModel Я использую следующие showProgressIndicator.onNext(true) для управления видимостью progressContainer во время загрузки сети.

class OrdersFragment : Fragment() {

    companion object {
        fun newInstance() = OrdersFragment()
    }

    private lateinit var viewModel: OrdersViewModel
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.orders_fragment, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel = ViewModelProviders.of(this).get(OrdersViewModel::class.java)

               viewModel.orders
            .doOnError { Log.println(Log.WARN, "Orders", "Not found") }
            .doOnNext { Log.println(Log.WARN, "Orders", it.newOrders.toString()) }
            .observeOn(AndroidSchedulers.mainThread())
            .map { orders ->
                val newOrders =
                orders.newOrders.map { order ->
                    OrderItemViewType.OrderRow(order, OrderType.NEW_ORDERS)
                }
                val enteredOrders = orders.enteredData.map { order ->
                    OrderItemViewType.OrderRow(order, OrderType.ENTERED_ORDERS)
                }
            }
            .subscribe { orders ->
                this.orders.clear()
                this.orders.add(0, OrderItemViewType.Header(OrderType.NEW_ORDERS, orders.newOrders.size))
                this.orders.addAll(orders.newOrders)
                this.orders.add(OrderItemViewType.Header(OrderType.ENTERED_ORDERS, orders.enteredOrders.size))
                this.orders.addAll(orders.enteredOrders)
                ordersAdapter.notifyDataSetChanged()
            }
            .addTo(this.disposeBag)

        viewModel.shouldShowProgress
            .map {
                if(it) {
                    View.VISIBLE
                } else {
                    View.INVISIBLE
                }
            }
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                //Avoiding the following crash for now
                //https://console.firebase.google.com/u/0/project/blazebites-e21f4/crashlytics/app/android:com.blazebite.kitchen2/issues/9c3a41b85fe4e94dd8adee3c6bde185a?time=1581379200000:1581465599000&sessionId=5E403F3F006000013B9F7D10397BD681_DNE_0_v2
                if(this.progressContainer != null) {
                    this.progressContainer.visibility = it
                }
            }
            .addTo(this.disposeBag)
    }

    override fun onDestroy() {
        super.onDestroy()
        this.disposeBag.dispose()
    }
}

Затем ViewModel

class OrdersViewModel : ViewModel(), KoinComponent {
    private val showProgressIndicator: PublishSubject<Boolean> = PublishSubject.create()
    val shouldShowProgress: Observable<Boolean>

    init {
        shouldShowProgress = showProgressIndicator

               orders = Observable
            .interval(0, 5, TimeUnit.SECONDS)
            .doOnNext { logger.write("Orders", "Attempting Order Retrieval") }
            .doOnNext { showProgressIndicator.onNext(true) }
            .filter { persistence.isLoggedIn }
            .doOnNext { logger.write("Orders", "Logged In") }
            .filter { persistence.accessToken.isNotEmpty() }
            .doOnNext { logger.write("Orders", "Have a valid token") }
            .filter { persistence.restaurantId > 0 }
            .flatMap { this.fullOrderData() }
            .doOnError { logger.write("Orders", "Might have been a bad request") }
            .doOnNext { showProgressIndicator.onNext(false) }
    }
}
...