1

So i am using Navigation in my main activity of my app and i have a fragment which is my start navigation fragment.

In this fragment, after it is created, in my presenter i post a thread to fetch data from the network. After data have been fetched, i am using the main thread to show the data to my screen.

The first time that the app runs, this is working fine.

However if user opens the drawer and selects again THIS fragment and not another one, fragment is recreated again meaning that it gets destroyed and created from scratch as Navigation Component is designed to do.

However this time, when my presenter posts thread fetching-data-thread and this gets finished and sends the results to the UI, fragment's isAdded() method returns false as well as getActivity is null.

Having that, means that i can't use the Activity Context (getActivity() is null or requireActivity() throws an illegal state exception) and consequently i cannot load images etc since i don't have the context available.

I highlight that this happens when user opens the drawer while this fragment is visible and selects again to navigate to this fragment from the drawer. In case that user navigates to another fragment and then presses the back button everything is ok.

Any idea how to handle this problem?

jvoyatz
  • 171
  • 1
  • 8

2 Answers2

0

Fragments are meant to be destroyed, as well as activities. You can never rely on android framework component lifecycle state, and because of it android architecture components were made. ViewModel, for example, can outlive it's host fragment.

But - viewmodel/presenter/controller is not a right place to perform network request and handle app logic, just because it's not their job (SOLID's S-single responsibility).

There is official guide to app architecture. Simply speaking, you have a layer for android-related code, where you update UI, layer for handling app logic (which is java/kotlin and android framework independent) and layer for requesting/holding data. So, during creation of your ui class you obtain viewmodel, which has reference to class that handle logic and exposes result to render in ui. Inner layers are persisted - view is not.

Community
  • 1
  • 1
Yrii Borodkin
  • 772
  • 5
  • 7
  • Firstly, thank you a lot for your response. Secondly, i am aware of Android Lifecycle and let me tell you that my presenter the only thing it does is to invoke my repository to fetch data and then after this task gets completed, it is responsible to pass the results to the UI. Moreover, i create my Presenter outside of the fragment using a pattern like "Manual Dependency Injection" as described [here](https://developer.android.com/training/dependency-injection/manual). – jvoyatz Feb 24 '20 at 08:21
  • so, if data gets saved in repository, it's really not a problem that ui is destroyed. When fragment get's recreated it's presenter has access to saved data and can just pass it to fragment. – Yrii Borodkin Feb 24 '20 at 11:35
  • Yes exactly. The problem was that my presenter was not informed regarding the new 'View' object aka the new Fragment instance. – jvoyatz Feb 24 '20 at 19:26
0

So, after testing and searching i found out the origin of the problem i described above.

I am nullifying my presenter's view in onDestroy/onDetach method of my Fragment. However when the replacement Fragment gets created, this new Fragment is firstly attached to the calling Activity and then, the old one gets destroyed.

Having in mind, that i inject my presenter into the Fragment instance, my presenter will be never null at the time that new Fragment gets attached and consequently, and considering that i create a new instance of my Presenter when it is null, the presenter instance that is being injected into the fragment is not aware of the new 'View' object.

As a result, when the results reach the UI thread through the callback this view object is 'not Added'.

jvoyatz
  • 171
  • 1
  • 8