I'm using this library in my app. The way I've written is that I have a MainActivity with the layout as provided by the library viz. something like this:
<SlidingPanel>
<MainContentLayout>
<SlidingPanelContentLayout>
</SlidingPanel>
The MainContentLayout is basically a FrameLayout where I load a fragment into. Now here's where it gets tricky--the fragment has code that accesses the slidingupPanel's layout components. When I type the component in Android Studio it automatically imports the correct synthetic property class file as import kotlinx.android.synthetic.main.layout_sliding_panel.* and even autocomplete works to show the correct fields as properties. However, when I run the app is crashes saying that field is a null. To fix this, I have to add (activity as MainActivity). as a prefix to all the fields. And when I run this, it fixes the issue.
Is there a cleaner way to do this because writing (activity as MainActivity). in so many locations seems annoying. Is there like a kotlin directive for this and why doesn't KotlinX view binding library auto-detect that the sliding panel layout is on a different layout and therefore write to correct convenience class to access this properly without crashing the app?
I understood your question like this: you are trying to access one of activity's views from fragment it hosts.
Such approach is not good as it couples activity and fragment (thus making fragment non reusable in other activities). If really needed, interaction between activity and fragment can be done using interface activity implements. However you need to keep in mind fragment's lifecycle (in other words activity reference is not always accessible inside fragment). Last but not least, nothing wrong with kotlin extensions.
Related
Lets say that in Components module I am creating a Fragment with layout file fragment.xml where one of the TextView is rendering android:text="#string/resource1"
Now I want to reuse the Fragment in App module but this time, the app would like to provide value that needs to be rendered. So far I have found only the option to create an open fun provideResource():Int on Fragment and inside set the TextView.setText(). The consumer of the Fragment will need to inherit the Fragment and provide the id in this method. But I don't like it. Is there a better way? Thanks.
Note : This is a question that I asked straight on the LightCycle project github. It's a great tool from SongKick to build a clean MVP architecture over your android app .
There is a thing that I miss thought, I have an activity with many fragments and many fragmentsPresenters.
Sometimes I do computation on my activity presenter and I want to send it to one or many of the fragment presenters (for example my table of content is displayes in the activity menu, and in a fragment that is shown full screen at the beginning).
How to I add a keep a reference of fragment presenters in my activity presenters (maybe it's not how I'm supposed to design it).
Second question. I have MyActivityPresenter that has two children : MyOnlineActivityPresenter and MyOfflineActivityPresenter.
MyActivityPresenter.newPresenter(Network.isNetworkAvailable(contexte), few other args) decides whearas an online or offline presenter is instanciated. So I should do something like :
#LightCycle
PlayerPresenter presenter = PlayerPresenter.get(NetworkUtils.isNetworkAvailable(this));
But I've been told that I should never use context that way as It could be null at the class instanciation moment. Is it indeed a problem ?
also should I pass the few others arguments that I have in the onCreate Bundle ?
And I don't use dependency injection at the moment.
I hope that I'm clear,
thanks again for this very useful lib
This is the answer they gave me
How to I add a keep a reference of fragment presenters in my activity presenters (maybe it's not how I'm supposed to design it).
It is not something in the scope of this library. I can see 2 solutions for you :
inject the same instance
provide an accessor to the presenter from the fragment. (which seems to be better for you).
But I've been told that I should never use context that way as It could be null at the class instantiation moment. Is it indeed a problem ?
also should I pass the few others arguments that I have in the onCreate Bundle ?
Same here.
You can use the app context which should be available and enough in your case
You can init this guy in the constructor because binding happens on create
Lets say I will be using several fragments(Action1Fragment, Action2Fragment etc.) within an activity(ActionActivity). I want to access some elements of activity object, or call some methods of ActionActivity. It is generally offered to create a event callback . What if I keep a reference to ActionActivity within Action1Fragment instead of keeping a reference to CallBackInterface which is actually implemented by ActionActivity since I will be using these fragments only within a particular activity.
I am kinda confused by the idea that Activity might be dead while reference of interface might still be alive(it sounds ridiculous when I read it again but it is OK if I managed to explain myself).
The Android Developer tutorials recommend that you use a callback interface on your fragments. The activity that hosts the fragment must implement the callback interface. The fragment does getActivity() and casts it to the callback interface, and then makes the callback.
This is the recommended way to promote a more modular design. It would not matter if your fragments will only ever work inside one activity. But if you want to make more generic fragments that could be used by different activities, then the above design pattern starts to become useful. (For example: a telephones fragment inside an person fragment and a company fragment.)
Suppose you do it the other way: the fragment does getActivity() and casts it to PersonActivity. The fragment then has access to all the public methods of PersonActivity. But this design pattern becomes much more ugly when you need the other activity to also use the fragment. The fragment would then have to be changed to first try and cast to PersonActivity, and if that throws, try the CompanyActivity.
The recommended design pattern basically gives you a way to make an activity compatible with the fragment instead of vice versa. The fragment only knows about the callback interface and not about any of the activities itself. The activities do know about the fragment because they implement the callback interface but they already knew about it because they constructed and initialized an instance of it.
Does that make sense?
I'm having a problem instantiating Fragments in my program using the Support Library implementation. Here's a brief description of the task I'm attempting to perform and some of my attempts which haven't yet borne fruit:
The UI of my application is subject to change to meet user preferences. In order to do this, I'm using a Fragment for each different layout and replacing the active Fragment in the UI at a given time as per the user's instructions. Here are some ways I've tried (and failed) to do this:
I've tried adding the Fragments as non-static inner classes in my Activity. This approach worked so long as the user did not rotate the device. As soon as the user rotated the device, the application crashed (this is true for Portrait -> Landscape rotation and for Landscape -> Portrait rotation). Upon checking the issue using the emulator, I was getting an InstantiationException. I checked SO for some help, which led me to:
Implement the Fragment as a static inner class. When the Fragment initiates, it will expand its layout, and then from later in the control flow of the Activity, I can do stuff to the Fragment's subviews (in particular, add listeners to the buttons). Unfortunately this didn't work because I couldn't refer to the Fragment's subviews using [frag_name].getView().findViewById(). Something about referencing static objects in a non-static context. Once again, I checked SO, which led me to:
Implement the Fragment as a separate class altogether from the Activity. This seems to be what the Dev docs on developer.android.com recommend. Upon doing this, everything seems to compile fine, but when I try to refer to the Fragment's subviews (once again, using [frag_name].getView().findViewById()), I get a NullPointerException. When I add System.out.println() statements across my code to find out exactly what is happening, I find that the print statement inside onCreateView in the fragment is never getting fired, which implies that onCreateView is never getting triggered.
So now, I'm stuck. What am I doing wrong? The precise implementation of this isn't as important as learning something from the experience so I can get better at Android development, so if seperate classes are better than static classes or vice-versa, I don't really care which I use.
Thanks.
Figured it out. Turns out that in order to do what I wanted, I had to register the Activity as a Listener to each of the Fragments and pass "ready to enable buttons" messages back and forth between the two. To anyone using this question for further research, the guide on how to do that is located on the Android Developer guide, here: http://developer.android.com/training/basics/fragments/communicating.html
I have an app with multiple activities and multiple layouts. However, one piece of layout is included on several activities. I also have a thread which updates this layout. However, when i switch activity it doesn't work. Since the layout is included the elements have the same ID's, shouldn't it just work? Or do I really need to fetch an object for each element in the layout and feed it into my thread in order to make it update the elements in a new activity?
You should run the update code for each Activity/View, although the XML included is the same, each is a different instance.
My suggestion is on Restart verify is there is any modification to do in each activity, a simple way is to each Activity extend a BaseActivity that has this code.
I include a layout for adverts in my app, but on each activity that uses it, the adverts need to be reloaded.
If I call an activity from one that is using the same included layout when I go back to the previous activity it's still there.
I guess this is what you are seeing....
So you can also save that data inside sharedPreferences (if it is little data and primitive objets or parceable objects).
Also you can extend the Application class and store the data there and update every activity inside the onResume() method. that i believe is the best way to handle this. and this is quite simple to do.
Ask google about extending the application class and he will provide tons of results on how to do it. its an easy way to pass data between activities and/or keep a reference to a single object which you will use throughout the app. Just be carefull to clear it when you wont need it anymore because it will stay in existance untill the application is finished() (which comes with the application extension living thru the whole application lifetime).