When I am using navigator, how do we hook into 'willFocus' and 'didFocus' events?
I am trying below code:
this.refs.sideBarNavigator.navigationContext.addListener('willFocus', this._navigatorWillFocus);
this.refs.sideBarNavigator.navigationContext.addListener('didFocus', this._navigatorDidFocus);
but the callbacks don't seem to be called when a scene is popped, pushed or replaced.
I am not sure if I am getting navigationContext correctly.
Related
I've been working on a project which needs to capture keystrokes from an external keyboard (a handheld barcode scanner really) anywhere in the app. Using react-native, this should be trivial, especially with the library react-native-keyevent.
Works perfectly on the initial load. I then navigate to another part of the app (using react-navigation) and try to scan a barcode; nothing happens. I replaced the react-native-keyevent overrides MainActivity.java with some simple Log.d("KeyEvents", "..."), overriding dispatchKeyEvent, onKeyUp, onKeyMultiple and onKeyDown. I only log, then call super.
Same behaviour. Logs fine until I navigate, then it stops. After investigating the Android docs, it seems Views can override key handlers, and thereby 'steal' keystrokes. However I'm stuck finding out which view steals the focus. Also there's really no keyboard handling in react-native by default, so to my understanding, everything should be passed on to the activity.
Wandering hopelessly around in the react-native codebase, I stumbled upon TVEventHandler which I use to log if a view requests focus:
import TVEventHandler from 'react-native/Libraries/Components/AppleTV/TVEventHandler';
(new TVEventHandler).enable('foo', function(){
console.log(arguments);
})
Right before the handlers stop working, this line indeed logs some focus events with a view tag. However, I don't know how to find out which view has a certain tag.
Can someone point me in the right direction where to look?
I'm writing an NPM module to emit an event from native code after the MainActivity is started, so that I'll be able to add a listener in componentWillMount() and do the things I want. I can write the listener code somewhere else but I want to access the props of the component.
I'm sending the event right after startActivity call, as the startActivity call is asynchronous it immediately sends the event even before the component from JS part is initialized. So, I'm not able to listen for the event.
Ultimately, I want to wait till the MainActivity is started so that the listener will be added then it'll be safe for me to emit event from native code.
Any ideas or pointers how to do it?
I figured out a way to finally achieve what I wanted. I defined a public static function in my native module file and called it from onCreate function of my app's MainActivity.java.
I successfully published the module to NPM...:D
https://github.com/vicke4/react-native-invoke-app
I have a simple game object (the main UI object) with OnApplicationPause that prints out the Pause status (true/false) in the debug log.
When I run it on android, and press the Home Button to leave the app, I see that the OnApplicationPause() is called twice in a row, with the same pauseStatus (true). The same happens when I reopen the app: the OnApplicationPause is called twice with Pause status false.
Why is it being called twice and can I avoid it? Am I doing anything wrong?
I also tried to create a separate GameObject, that includes the same debug code. The issue doesn't occur there - only in my main UI object.
Are you 100% sure that your script containing the OnApplicationPause() method is not present twice in the Scene when Pause occurs? or present on a previous Scene on a DontDestroyOnLoad GameObject?
OnApplicationPause is called on each active MonoBehaviour when pause occurs.
So having two Debug.Log means two scripts instances running if you don't call it manually yourself.
I am having an app which is retrieving data in the main activity and sending an event to all fragments as soon as it is available. So for the first start it looks like this:
App starts (fragments are initialising in the background) -> feed download -> notification sent to fragments -> fragments initialise UI
Everything's fine so far. BUT, what if I am resuming the app. The data will be still cached, so i will send the event immediately on app resume, and therefore it can happen that my fragments are not even ready for receiving the event -> no fragment UI update!
Or the event is triggered and received in the fragment, but the fragment is not ready for the UI update, cause it still hasn't inflated the layout -> NullpointerException
Or the fragment receives the event, but is not attached to the activity anymore -> another Exception.
There are ways to deal with single issues, but overall it is complicating the architecture a lot.
Somehow I tried a lot of things (playing around with Otto bus) but somehow I can't find any architecture which is working for making a central datasource available to all activities and fragments in the app.
How do you supply your fragments with data if you don't want to use bundles?
First of all a Fragment should be independent from other parts of an app. Moreover it shouldn't know parent activity: getActivity method should return just an Activity which could be casted to some interface.
an Activity shouldn't be a "data downloader". Basically activity is a View which receives various system and user events and displays particular state. For instance when the system creates activity it calls method 'onCreate' where activity should create/arrange fragments and views.
there is should be some manager or controller(call it as you wish) which knows where and how to get data for views. For instance if there is no internet connection it loads data from local database otherwise it makes network request.
So roughly speaking flow should look like this:
fragment(or activity) has reference to the DataManager. The fragment subscribes on FeedDataEvent in the onResume method. When fragment wants(onResume method for example) to show some data to the user it calls DataManager.loadFeed() and displays to the user "loading..."
DataManager checks if there is Task which is loading data from network. If there is no such fast it starts it.
When data is downloaded DataManager emits FeedDataEvent.
If the fragment is still visible it receives that event and shows data. If the user left the app fragment unsubscribed(in the onStop method) from FeedEventData and will not receive that event.
There is subtle thing with requests caching(making network request on every onResume is not very good idea) but it depends on particular app.
PS Almost all this things are implemented in RoboSpice and some other libraries.
I'm using PhoneGap and jQuery Mobile to develop an Android app.
I'm trying to bind a function call to the event of the user leaving the page (back button or clicking some other link).
What I have so far:
$(window).unload(function () {
//my function
})
But it does not work.
You should be using the pagebeforehide of jQuery Mobile . From jQuery Mobile documentation:
pagebeforehide event:
Triggered on the "fromPage" we are transitioning away from, before the actual transition animation is kicked off. Callbacks for this event will receive a data object as their 2nd arg. This data object has the following properties on it:
nextPage (object)
A jQuery collection object that contains the page DOM element that we are transitioning to.
Note that this event will not be dispatched during the transition of the first page at application startup since there is no previously active page.