The docs for RefreshIndicator suggest you can programmatically trigger the refresh behaviour via the RefreshIndicatorState class.
How do I access an instance of this class, assuming I've added a RefreshIndicator widget to my application? I can't see a property to access it and I'm assuming createState() is only used by the Flutter framework.
To avoid an XY problem, I should explain my reason for doing this is to perform a visually pleasing refresh of my list when my user first opens the app. The list will be empty initially and the refresh will poll my server for data.
See https://docs.flutter.io/flutter/material/RefreshIndicatorState/show.html and a usage example in the Flutter Gallery
Essentially
var indicator = new GlobalKey<RefreshIndicatorState>();
and then
indicator.currentState.show();
after it's built.
Related
I am building a Workshop App which will be used for data entry by a large number of operational staff members (> 200).
I would like to implement the following set-up:
The staff will enter the data on existing Ontology Objects. To facilitate this, I embedded a Foundry Form into the Object View, and set-up a corresponding write-back data set.
The Ontology Objects in question will be displayed in an Object Table in Workshop.
The staff member will select an Object from the Object Table.
The selected Object will be opened in an Object View.
The staff member will enter data on the Object View (Foundry Form being displayed here).
I need to make sure that no concurrent data entry can/will happen. How can I achieve this?
I am thinking about removing any Object which is opened in the Object View from the Object Table, but I am not sure if this is the best solution to the problem or how to achieve the removal from the table.
I am assuming that this must be a common problem and there would be a Design Pattern/Standard Functionality to solve this.
You'll have the best behavior here if you replace your Foundry Form with Foundry Actions. These actions are defined in the Ontology Management App and provide a more robust security model for managing object edits and are more tightly integrated into the various object-layer tools in Foundry.
Then in your Object View, rather than using the Foundry Forms widget, choose to create a new "Workshop-backed" Object View tab - this option is under the dropdown next to the New Tab button - and within the Workshop module use the Inline Action Form to embed the action form that you've configured in the Ontology Management App, supplying the variable representing the current object as the default for the object parameter in the Action.
With regards to simultaneous edits, in Actions, when the form is populated (i.e. when that tab is opened), the version of the underlying object(s) are registered. When the edit request is submitted, the current version of the object is checked, and if the version is different (i.e. there have been edits applied since the form was loaded) the user will be presented with message to the effect that the object has been updated and the edits will not be applied.
This protects against the case of a user overwriting a near-simultaneous edit without reviewing the changes first and does so at the writeback layer, rather than with logic in your application front-end.
There is not currently an approach to reflect real-time user interaction between two Workshop sessions. For instance, there is no way for the session of User A to "know" that User B has opened Object X in their session and is making a change.
If you wanted to do something for a bit of convenience or display signaling, you could create a small object type related to your main object - something like "Edit Lock" that looks like:
| id | primary_object_id | user_id | timestamp | timeout
And then in your Workshop app, there's a button above the table that says "Edit Selected Object".
When you click this button, you trigger an Action to create a new "edit lock" object populated with the current user and the current timestamp and say a timeout of 15 minutes from now.
Then in the object view for the primary object in question, on the same tab where you have the edit form embedded, you can create a variable that gets the edit locks associated with that object via a search around and use a Function to create a boolean variable if there is an "active" edit lock. And use this to conditionally show a banner to the user or otherwise give them a visual indication that another user has indicated they're making changes.
This won't push to the other session, and it'd be just for display purposes, the real protection still comes from the underlying object versioning that Actions enforces, but it might be a nice user affordance to layer on top if you really expect to commonly run into this situation.
So I'm seeing some bizarre behavior in an appwidget that I wrote.
The widget itself is quite simple - it reads a few values from persistent storage and then displays them as text. Nothing fancy in the layout - just a FrameLayout root element with some Linear Layout and TextView children.
The widget has a simple configuration activity associated with it.
The bizarre behavior is that the widget will initially show "Problem Loading Widget" after the user closes the configuration activity, and then after a few seconds it shows a "Google Sound Search" button (and clicking on the button actually does launch Google Sound Search). Then, after a few more seconds, it finally shows the expected display.
I am away from my code right now, so I'll have to wait until tonight to post code snippets. However, in the meantime, can anyone provide some insight into how such a thing could happen? Has anyone else ever experienced this? How could another widget "hijack" mine?
Thanks,
-Ron
Here are some screenshots:
There are a couple of issues with your widget and there are answers to all of them (although you didn't post any code so some of my statements are based on assumptions):
"Problem loading widget": this is the default view Android uses before the widget is initialized and the layout updated. Simply add the following line to your widget xml configuration (to show a loading message instead of the problem message):
android:initialLayout="#layout/my_cool_widget_loading_message"
If the widget shows the wrong layout then you probably have an issue in the widget's onReceive method. onReceive is called for all the widgets no matter whether the broadcast is for that specific widget. Android's AppWidgetProvider filters the broadcasts by appwidget Id and dispatches to the other methods (like onUpdate).
See also: https://developer.android.com/reference/android/appwidget/AppWidgetProvider.html#onReceive(android.content.Context, android.content.Intent).
If you override onReceive (which I assume you do), you need to call through to super.onReceive(Context, Intent) to make sure your other methods don't get calls meant for other widgets.
Now for the configuration of the widget. If you follow the Google documentation then it will all work nicely. The only improvement I'd do is what my other answer that you reference suggests (https://stackoverflow.com/a/14991479/534471). This will NOT send out two broadcasts. The setResult()/finish() part does only terminate the config Activity and let Android know whether to actually add the widget or not (depending on whether the result is RESULT_CANCELED or RESULT_OK.
From your own answer I can see why your code wouldn't work. The code is:
Intent intent = new Intent();
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {mAppWidgetId});
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, intent);
sendBroadcast(intent);
finish();
First of all there's no need to add the appWidgetId twice, use the AppWidgetManager.EXTRA_APPWIDGET_IDS version and you're good. Second you're using the same Intent to return as a result for the Activity. AFAIK it's not documented what happens when you do set an action on that Intent but my experience with Android widgets is that you need to stick exactly to the documentation or you'll end up having strange issues (like the ones you encounter). So please use two different Intents.
Activity result:
Intent resultValue = new Intent();
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, resultValue);
finish();
Broadcast:
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE, null, this, MyWidget.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {mAppWidgetId});
sendBroadcast(intent);
ok, so I figured it out. Posting here in case anyone else runs into this. I think that the Android Developer docs are a little misleading here.
The problem was that in my configuration Activity, I had this code at the end:
Intent intent = new Intent();
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {mAppWidgetId});
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, intent);
sendBroadcast(intent);
finish();
Providing an intent with the extra EXTRA_APPWIDGET_ID is recommended by the documentation provided by google.
However, that same document says that you have to update the widget's view by creating a RemoteView and calling AppWidgetManager.updateAppWidget() like so:
RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.example_appwidget);
appWidgetManager.updateAppWidget(mAppWidgetId, views);
I didn't like the idea of placing the presentation logic in both the configuration activity and the widget class, so I instead decided to broadcast an intent at the end of the configuration activity to tell the widget to redraw itself. That's why I have setResult() AND sendBroadcast() at the end of the activity. The documentation further states that the onUpdate() callback will not be called when using a configuration activity. So this seemed neccessary. I added the ACTION_APPWIDGET_UPDATE and the EXTRA_APPWIDGET_IDS to the intent so that it would trigger the onUpdate() method. This practice was recommended by this SO answer (albeit without being included in the activity result intent - but I tried separating the two and it had no effect).
Now I'm not certain exactly how the "Google Sound Search" widget got in there, nor do I fully understand the mechanics of how the intents interacted to produce the observed results. However, as soon as I replaced my code above with the code stated in the docs, the widget was updated properly.
Intent resultIntent = new Intent();
resultIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, resultIntent);
finish();
This seems to contradict the documentation's statement that the configuration activity must update the widget's view. Simply providing the configuration activity result as below triggers the onUpdate() method in the widget, thus allowing the widget to redraw itself. I confirmed the behavior on an emulator running API 23 and also on a Samsung device running Samsung's android flavor.
I am working on a fairly simple Heat Map application where the longitude and latitude of the points will be stored in a SQL Server database. I have been looking at an example that uses an array of objects as follows (eliminated a lot of data for brevity):
/* Sample data to demonstrate Bing Maps Heatmap */
/* http://alastair.wordpress.com */
var CrimeData = [
new Microsoft.Maps.Location(52.67280, 0.94392),
new Microsoft.Maps.Location(52.62423, 1.29493),
new Microsoft.Maps.Location(52.62187, 1.29080),
new Microsoft.Maps.Location(52.58962, 1.72228),
new Microsoft.Maps.Location(52.69915, 0.24332),
new Microsoft.Maps.Location(52.51161, 0.99350),
new Microsoft.Maps.Location(52.59573, 1.17067),
new Microsoft.Maps.Location(52.94351, 0.49153),
new Microsoft.Maps.Location(52.64585, 1.73145),
new Microsoft.Maps.Location(52.75424, 1.30079),
new Microsoft.Maps.Location(52.63566, 1.27176),
new Microsoft.Maps.Location(52.63882, 1.23121)
];
What I want to do is present the user with a list of some sort that displays all the data sets that exist in the database (they each have a name associated with them) and then allow the user to check all or only a select few. I will then need to generate an array like the above to create the heat map. Any ideas on a good approach to this?
What you trying to achieve is more related to a web developement rather than only related to Bing Maps.
To summarize, you have multiple ways to do this but it really depends on what you are capable to do and what you need in the interface.
What process/technology?
First, you need to determine what process you want to follow to display the data and it will set the technology that you will use. The questions that you need to ask yourself are:
Do you want to be able to change the data sets dynamically without refreshing the whole page?
If yes, it means that you will have to use asynchronous data loading through a dedicated web service in order to avoid loading all the information at the initial load of the page.
Do you have lots of data to load?
If so, it might comfort you with asynchronous loading to avoid loading all data.
If not loading every elements in multiple arrays might be the simplest solution.
Implementation
So now, you want to create a web service to load the data asynchronously, you can take a look at the following websites :
http://www.asp.net/get-started
http://www.stefanprodan.com/2011/04/async-operations-with-jquery-ajax-and-asp-net-mvc/
There might be interesting other website, you will be able to find them. If needed, add comment and I'm sure the community will help you.
If you want to generate the data directly in the script, it could be simple as you can compose the JavaScript directly in your dynamically created HTML page (in your ASP.Net markup code or whatever technology you're using).
Box:// seems to open the app, however I am not able to discern how to target a specific file.
Currently we don't have support for this, but it is a great idea that we'll consider for our roadmap.
We actually do support this. The best way to add this integration into your app is to use our OneCloud AppToApp framework (additional information available here http://developers.box.com/the-box-sdk-for-onecloud-on-ios/)
This is easy using the app-to-app framework. You just need to call BoxAppToAppAPI's sendFileDownloadRequestToApplication:withMetaData: if you want an app to go to a particular file and in Box's case download/preview it.
To make it go to the Box app you can simply pass in [BoxAppToAppApplication BoxApplication] in the first parameter.
As for the metadata parameter, you can create it with BoxAppToAppFileMetadata's appToAppFileMetadataWithFileName:fileExtension:folderPath:mimeType:fileID:folderPathByID:exportToken:username:
Assuming your app already integrates with the Box API via the SDK or otherwise, it should be able to get all of that information easily.
If the mimeType is not known, nil can be passed in. Also, nil can be passed in for the exportToken if the file was not exported out of the Box app (with the AppToApp framework, a roundtrip scenario is also supported where the user starts in the Box app, picks a file to view/edit/etc in your app, and then sends it back to Box to upload). So if it's not a round-trip, it's just a one-way from your app to Box, use nil for the exportToken.
Before doing this, you can also check if the Box app is installed by checking for [[BoxAppToAppApplication BoxApplication] isInstalled].
Below is a fictional example (the values are made up):
BoxAppToAppFileMetadata *metadata = [BoxAppToAppFileMetadata appToAppFileMetadataWithFileName:#"fileName"
fileExtension:#"png"
folderPath:#"All Files/Folder1"
mimeType:nil
fileID:[NSNumber numberWithLongLong:123456]
folderPathByID:#"0/12345"
exportToken:nil
username:#"username#email.com"]
BoxAppToAppStatus status = [BoxAppToAppAPI sendFileDownloadRequestToApplication:[BoxAppToAppApplication BoxApplication]
withMetaData:metadata];
Ok so here is what is happening:
I have a client that I am building an application for. My client has a flowchart that they would like posted on the front page of their application. Check. My client then wants this flowchart to be set up as an image map so that a user could click one of the boxes in this flowchart and be taken to a report in another part of the application. Check.
All of that is elementary and, in a technical sense, works. The issue is, and it is an issue I have encountered before with APEX, is that every time a user clicks one of these links it takes them to the login screen. It seems that linking directly to a page's URL breaks the session and requires you to login again, even if you are linking from one page in the application to another in the same application.
I have played with all of the authentication settings in a hopes of fixing this and tried to determine what is breaking the session exactly but with no luck.
Has anyone else had this problem and could share their method for fixing it? I really cant have users logging in every time they click a link and I also cannot simply remove the authentication on the pages. Thanks in advance.
You should pass on the session id in your links. If you don't, then apex will see this as a new session. You can tell from the url: take note of the session id in your url when you are on your image map. When you select an application, take another look at the session id part in the url. If they are different, then you are starting a new session each time.
/apex/f?p=190:90:1674713700462259:::::
190 -> application id
90 -> page id
1674713700462259 -> Session id
To pass on the session, it depends where you construct your links.
In PLSQL, you can find it through :SESSION or :APP_SESSION
For example, in a plsql dynamic region: htp.p('the session id is '||:SESSION);
In javascript code you can use $v("pInstance") to retrieve the value dynamically, or use &APP_SESSION. which will have the value substituted at runtime.
Small example:
function printsome(){
var d = $("<div></div>");
d.text('&APP_SESSION. = ' + $v("pInstance"));
$("body").append(d);
};
So you probably just need to alter the construction of your link somewhat to include the session!
I was assuming the binding variables will do the job. But they were helpless.
Best way is to pass the current session id to an item then use the item value in the link.
f?p=&APP_ID.:32:&P31_SESSION.:::P32_CUSTOMER_ID:#CUSTOMER_ID#