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.
Related
I have the following structure for my app, where ChatScreen contains the ChatHeader and the ChatFooter.
---ChatHeader.dart --- MessageDao.dart
ChatScreen.dart ---
---ChatFooter.dart
In the ChatHeader widget, I call another widget called MessageDao.dart. This widget generates the button that the user can press on the ChatHeader widget to play audio.
In the ChatFooter widget, this widget contains a different button that the user can press to record using their mic.
When I play audio using the button from ChatHeader -> MessageDao, this works just fine. However, if I click the button in the ChatFooter widget to start recording while in the middle of playing audio from the first button, this audio doesn't stop playing. It keeps playing while I'm recording. I have a stopPlaying() function in MessageDao that I can use, but I'm not sure how to call a function in widget A from widget B.
Or in other words, how do I call MessageDao.stopPlaying() from inside ChatFooter.dart?
With this type of situation, the ideal solution is to take a page out of React and 'lift the state up'; this means that whatever method is on the child should be lifted to a higher node in the widget tree (e.g. ChatScreen) and then pass the function down to the nodes that use it (ChatHeader and ChatFooter). You could also try leveraging InheritedWidget after 'lifting state up' and avoid sending methods down a chain of widgets.
Now, this is a recurring theme with Flutter apps (and overall declarative frameworks) and is a problem that can have multiple solutions. My suggestion would be that you take a look at different state management options like bloc, provider, mobx, riverpod, rxdart, redux or event_bus_plus just to mention a few. Said libraries will give you the abstractions you need for each use case and help you avoid implementing really complex logic that you might need to solve problems similar to this one by yourself.
Of course, this is an important decision for your project so I suggest you take a good look and choose whatever you feel comfortable with or is similar to something you have worked on before.
Good luck my fellow Flutter developer, choose wisely :P
You can use some event mechanism to notify MessageDao about an event in your app, e.g., AudioRecordingStartedEvent.
On MessageDao you subscribe on the event and stop the playing audio,
On ChatFooter you fire the event.
On pub.dev a lot of libraries that implement EventBus, e.g. event_bus_plus
We are tracking activity screen using firebase
Here is the code.
mFirebaseAnalytics = FirebaseAnalytics.getInstance(this);
mFirebaseAnalytics.setCurrentScreen(this, "HomeActivity", this.getClass().getSimpleName());
For some of our screes we are using controller using this library, https://github.com/bluelinelabs/Conductor
How can we track these controllers ?
if we are using this code app is getting crashed
mFirebaseAnalytics = FirebaseAnalytics.getInstance(getActivity().getApplicationContext());
mFirebaseAnalytics.setCurrentScreen(getActivity(), "testController", fragment.getClass().getSimpleName());
Screen Tracking on Firebase is based on the automatically collected user engagement event by design. The screen view event is triggered when the transition from one screen to another screen occurs.
In absence of screens or activities in background, GA for Firebase won't be able to track the screen event for that activity.
I have a cordova (ionic) app that facilitates entering a lot of form data. This form data is saved to localStorage until it is ready to be published.
So keep the app quick I am not saving to the disk everytime and input changes. I am saving when the user navigates away from the page.
The problem I'm having is that the user may enter a lot of data on one page, and close the app without navigating. This is an obvious use case but I'm not sure how to get in front of it without frequently going back to the disk.
Is there a way I can quickly save when the app is exited? I know I can listen to the "pause" event in cordova apps but is that the same when the app is exited? Does an exit emit "pause" ?
If not, what are some strategies for handling this?
TLDR: Listening to the pause event is the right strategy.
The pause event fires when the native platform puts the application
into the background, typically when the user switches to a different
application.
Source
The pause event is the only way to let you know your app is being put in the background. On some mobile platforms you don't even have the possibility to exit your app (in iOS for example), as the platform is managing this for you. So listening to the pause event is your only choice as you loose control once the app is paused. Therefore listening to the pause event is the right strategy.
See following code snippet:
document.addEventListener("pause", onPause, false);
function onPause() {
// Save the application state here
}
In detail I have implemented a storage service with a save-method, which is called in the OnPause-handler.
Pause only fires when going to background. Why you say "to keep the app quick"? it's javascript, you can save to disk every field when is filled and it can be asynchronous.
function onLoad() {
document.addEventListener("deviceready", onDeviceReady, false);
document.addEventListener("pause", onPause, false);
function onDeviceReady() {
var pageNow = document.getElementsByTagName(body);
var currentPage = JSON.stringify(pageNow);
localStorage.setItem("uiState", currentPage);
}
function onPause() {
//retrieve info here
var pageShow = document.getElementsByTagName(body);
let techStack = localStorage.getItem("uiState");
// JSON.parse(techStack); //unnecessary because the parser will detect HTML
pageShow.innerHTML(techStack);
}
}
you can get the current state of the UI in any element, just use a different selector.
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 have just upgraded jquery mobile to beta 2(from beta 1) and I am now receiving multiple click events if i go back into a page after pressing back, each time I go back in it adds another to the click so the alert fires however many times you go into the page
I have also noticed that clicks/taps seem to go through the current page and clicking on pages hidden by view - seems really strange but I am thinking they are probably linked.
It is as if it is creating multiple versions of the same page and when you go back into it loads a new one causing there to be two click events.
Here is a snippet of the code which is being fired
$('#click_me').live('vclick', function() {
alert('clicked');
});
Hopefully this makes sense and anyone can shed any light on what might be going on?
You've probably solved this by now, but you need to use the pagecreate event.
#Phill's suggestion of:
$('div').live('pageshow',function(event, ui){
$('#click_me').click(function() {
alert('clicked');
});
});
Unfortunately won't help, but you can solve the issue if you change pageshow to pagecreate
$('div').live('pagecreate',function(){
$('#click_me').click(function() {
alert('clicked');
});
});
If you're not using AJAX to load your pages, make sure also to change live to bind.
I had this same issue myself and this has solved it completely for me.
UPDATED:
I think the reason is you have the click event tied to the live event, so evrytime you navigate to that page it triggers the click event. try something like this:
$('div').live('pageshow',function(event, ui){
$('#click_me').click(function() {
alert('clicked');
});
});
or just use the click event
$('#click_me').click(function() {
alert('clicked');
});
When Beta 2 was released they are deprecating vclick
http://jquerymobile.com/blog/2011/08/03/jquery-mobile-beta-2-released/
Backtrack: We’ve switched back from vclick to click for links
In Beta 1, we decided to use our custom vclick event for handling Ajax
links to improve responsiveness and to hide the URL bar on the iPhone
and Android phones. Even though we did quite a bit of testing before
landing this for Beta 1, we began to hear feedback that this change
was causing some significant issues out in the wild including:
Multiple click events causing navigation and form element issue –
In certain situations, when tapping an element, tap/click events seem
to fire twice on links and is due to edge cases where the target of
the touch event and mouse event don’t match due to how the browsers
calculate tolerances for these events. This is most pronounced on
Android 2.1, but affected most WebKit-based browsers to varying
degrees when a tap events occured near the edge of an element.
Click handlers in custom scripts didn’t “work” anymore – if a
script bound only to click events on the document, the global vclick
feature could interfere because the touch events may supercede click
events so it events wouldn’t appear to trigger.