4

I have a system that handles errors and progressbar in a baseview interface. I implement the interface in my fragments and activities and pass the neccesary views via overriden getters like

    override val mContentView: View
    get() = contentView

where contentView is a view with id of "contentView" supplied through kotlin android extensions. contentView is the root view of a fagment needed by Snackbar to show errors.

In one of my views I get an exception

contentView must not be null

While the view is inflated and the fragment that has it is visible.

the weird thing is that if I access contentView in onViewCreated the error goes away!

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    contentView.let {

    }

}

Can someone please explain what is going on?

ps1: I'm accessing the view with RxJava2 but its on Rxandroids mainThread

ps2: A possible hint might be that the exception stack trace is a warning not a error(Not shown in logcat level error or debug)

ps3: The full stack trace

 02-25 11:29:45.814 27055-27055/com.beguchi.android.peyk W/System.err: io.reactivex.exceptions.OnErrorNotImplementedException: contentView must not be null
02-25 11:29:45.814 27055-27055/com.beguchi.android.peyk W/System.err:     at io.reactivex.internal.functions.Functions$OnErrorMissingConsumer.accept(Functions.java:704)
02-25 11:29:45.814 27055-27055/com.beguchi.android.peyk W/System.err:     at io.reactivex.internal.functions.Functions$OnErrorMissingConsumer.accept(Functions.java:701)
02-25 11:29:45.814 27055-27055/com.beguchi.android.peyk W/System.err:     at io.reactivex.internal.observers.LambdaObserver.onError(LambdaObserver.java:77)
02-25 11:29:45.815 27055-27055/com.beguchi.android.peyk W/System.err:     at io.reactivex.internal.observers.LambdaObserver.onNext(LambdaObserver.java:67)
02-25 11:29:45.815 27055-27055/com.beguchi.android.peyk W/System.err:     at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal(ObservableObserveOn.java:200)
02-25 11:29:45.815 27055-27055/com.beguchi.android.peyk W/System.err:     at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run(ObservableObserveOn.java:252)
02-25 11:29:45.815 27055-27055/com.beguchi.android.peyk W/System.err:     at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:109)
02-25 11:29:45.815 27055-27055/com.beguchi.android.peyk W/System.err:     at android.os.Handler.handleCallback(Handler.java:790)
02-25 11:29:45.815 27055-27055/com.beguchi.android.peyk W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:99)
02-25 11:29:45.815 27055-27055/com.beguchi.android.peyk W/System.err:     at android.os.Looper.loop(Looper.java:164)
02-25 11:29:45.815 27055-27055/com.beguchi.android.peyk W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:6494)
02-25 11:29:45.815 27055-27055/com.beguchi.android.peyk W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
02-25 11:29:45.815 27055-27055/com.beguchi.android.peyk W/System.err:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:440)
02-25 11:29:45.815 27055-27055/com.beguchi.android.peyk W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
02-25 11:29:45.816 27055-27055/com.beguchi.android.peyk W/System.err: Caused by: java.lang.IllegalStateException: contentView must not be null
02-25 11:29:45.816 27055-27055/com.beguchi.android.peyk W/System.err:     at com.beguchi.android.peyk.userInterfaces.main.idle.IdleFragment.getMContentView(IdleFragment.kt:32)
02-25 11:29:45.816 27055-27055/com.beguchi.android.peyk W/System.err:     at com.beguchi.android.peyk.scafolding.general.BaseView$DefaultImpls.renderError(BaseView.kt:24)
02-25 11:29:45.816 27055-27055/com.beguchi.android.peyk W/System.err:     at com.beguchi.android.peyk.scafolding.general.BaseFragmentView.renderError(BaseFragmentView.kt:13)
02-25 11:29:45.816 27055-27055/com.beguchi.android.peyk W/System.err:     at com.beguchi.android.peyk.userInterfaces.main.idle.IdleFragment.renderError(IdleFragment.kt:102)
02-25 11:29:45.816 27055-27055/com.beguchi.android.peyk W/System.err:     at com.beguchi.android.peyk.scafolding.general.BaseView$DefaultImpls.renderCommon(BaseView.kt:18)
02-25 11:29:45.816 27055-27055/com.beguchi.android.peyk W/System.err:     at com.beguchi.android.peyk.scafolding.general.BaseFragmentView.renderCommon(BaseFragmentView.kt:13)
02-25 11:29:45.817 27055-27055/com.beguchi.android.peyk W/System.err:     at com.beguchi.android.peyk.userInterfaces.main.idle.IdleFragment.render(IdleFragment.kt:83)
02-25 11:29:45.817 27055-27055/com.beguchi.android.peyk W/System.err:     at com.beguchi.android.peyk.userInterfaces.main.idle.IdlePresenter$bindObservables$3.accept(IdlePresenter.kt:48)
02-25 11:29:45.817 27055-27055/com.beguchi.android.peyk W/System.err:     at com.beguchi.android.peyk.userInterfaces.main.idle.IdlePresenter$bindObservables$3.accept(IdlePresenter.kt:15)
02-25 11:29:45.817 27055-27055/com.beguchi.android.peyk W/System.err:     at io.reactivex.internal.observers.LambdaObserver.onNext(LambdaObserver.java:63)
02-25 11:29:45.817 27055-27055/com.beguchi.android.peyk W/System.err:   ... 10 more
saiedmomen
  • 1,401
  • 16
  • 33
  • 2
    If you get an exception you also get a stacktrace to it. Could you add this as well? – tynn Feb 25 '18 at 07:57
  • sorry. It's done – saiedmomen Feb 25 '18 at 08:08
  • Consider loosing the `m` prefix. From the stacktrace I'd assume that your Rx source emits before the view is fully created and thus rendering happens too early. `renderCommon()` directly goes to `renderError()` as well; is this because of a try-catch for the same error? – tynn Feb 25 '18 at 08:25
  • And accessing it in onViewcCreated fixes it? .No the view is inflated and visble when it happens .No its a when block – saiedmomen Feb 25 '18 at 08:28

2 Answers2

2

In onCreateView() a getView() is null, see Kotlin Android Extensions and Fragments. So, initialize views in onViewCreated() or write view.contentView.....

Also, use let with preceding ?.: contentView?.let{ }.

CoolMind
  • 26,736
  • 15
  • 188
  • 224
2

contentView which you are referring to with Kotlin synthetic extensions, it just gives you the reference to view object (in your case content View).

If you access this object before layout or view is created , it will return null

Now in Fragment. , It is in the onViewCreated() where your view is created (build or initialized) . So is your contentView is created (is initialized)