How to know FirebaseRecyclerAdapter query is zero or not, exist or not - firebase

How to know FirebaseRecyclerAdapter query is zero or not, exist or not
I find some instructions on
https://github.com/firebase/FirebaseUI-Android/tree/master/database
it says:
Data and error events
When using the FirebaseRecyclerAdapter you may
want to perform some action every time data changes or when there is
an error. To do this, override the onDataChanged() and onError()
methods of the adapter:
FirebaseRecyclerAdapter adapter = new FirebaseRecyclerAdapter<Chat, ChatHolder>(options) {
// ...
#Override
public void onDataChanged() {
// Called each time there is a new data snapshot. You may want to use this method
// to hide a loading spinner or check for the "no documents" state and update your UI.
// ...
}
#Override
public void onError(DatabaseError e) {
// Called when there is an error getting data. You may want to update
// your UI to display an error message to the user.
// ...
}
};
When I tried to use as follow:
mAdapter = new FirebaseRecyclerAdapter<Place, PlaceViewHolder>(options)
{
#Override
public void onDataChanged(DataSnapshot dataSnapshot)
{
// Called each time there is a new data snapshot. You may want to use this method
// to hide a loading spinner or check for the "no documents" state and update your UI.
// ...
if (dataSnapshot.exists())
{
Log.d(TAG,"data exists");
}
else
{
Log.d(TAG,"No data exists");
}
}
#NonNull
#Override
public PlaceViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i)
{
Error message is:
Method does not override method from its superclass
So how can I solve this problem, Thank you.

I found the answer from another page:
https://www.programcreek.com/java-api-examples/?api=com.firebase.ui.database.FirebaseRecyclerAdapter
#Override
public void onDataChanged()
{
// Called each time there is a new data snapshot. You may want to use this method
// to hide a loading spinner or check for the "no documents" state and update your UI.
// ...
if (getItemCount() == 0)
{
Log.d(TAG,"No data exists");
}
else
{
Log.d(TAG,"data exists");
}
}

Related

JavaFX - Call "updateMessage" for TextArea from background Task - Two problems found

I am having two problems when trying to use "updateMessage" in a JavaFX task.
Issue #1
seems to be a known behavior, but I am not yet sure how exactly I can workaround it.This one is not (yet) critical to me.
The problem is that not all the updates I am performing in a background Task are displayed in the UI (at least the UI does not hang/freezes anymore, which was my initial issue).
My Code of the UI part:
TextArea console = new TextArea();
Button button01 = new Button("Start");
button01.setOnAction(new EventHandler() {
#Override
public void handle(Event event) {
if (ms.getState() == State.READY) {
ms.messageProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observable,
String oldValue, String newValue) {
console.appendText(newValue+"\n");
}
});
ms.start();
}
}
});
My Service:
public class MyService extends Service<Object> {
#Override
protected Task createTask() {
//here we use "MyTask" first to show problem #1
MyTask ct = new MyTask();
//here we use "MyTask2" first to show problem #2
// MyTask2 ct = new MyTask2();
try {
ct.call();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("MyService end");
return ct;
}
}
My Task (#1)
public class MyTask extends Task<Object> {
#Override
public EventHandler<WorkerStateEvent> call() {
System.out.println("call() is called");
if (Thread.currentThread().getName().equals("JavaFX Application Thread")){//yes, this might not be right, but if I do not do this, my stuff is executed twice because "call()" is called twice, but the textarea area is just updated in the second run (the non javafx application thread).
return null;
} else{
//actually here I want to do some 'heavy' stuff in the background
//and many things of this heavy stuff should be displayed / logged within the UI
//but very likely (hopefully) new messages (updateMessage) will not be send as fast as in the following loop
for (int i=0;i<10000000;i++){
updateMessage("This is update number'"+i+"' from the background thread");
}
Platform.runLater(new Runnable() {
#Override
public void run() {
try{
//here is the chance to get back to the view
}finally{
}
}
});
return null;
}
}
This basically works, but not every single loop is displayed in the UI.
How do I (correctly) make sure every loop is displayed?
Screenshot: Messages are displayed but not for every loop
Issue #2
Currently blocks my attempt to bring my little text-based game into a JavaFX application.
The main problem is that I am able to call "updateMessage" from the Task directly (see above), but not from a another (sub-)class which I would need to bring all message updates from my game (each message describes the progress of the game) to the UI.
The Task I use (Task #2):
public class MyTask2 extends Task<Object> {
#Override
public EventHandler<WorkerStateEvent> call() {
// ...
UITools myTools = new UITools();
myTools.logToUITest("Just one simple message");
// ...
Platform.runLater(new Runnable() {
#Override
public void run() {
try{
//here is the chance to get back to the view
}finally{
}
}
});
return null;
}
and the (sub-)class that I want to use to do the updateMessage (actually in my little game there would be even more classes that are called during the game and almost all of them trigger an update/message).
public class UITools {
public void logToUITest(String message){
updateMessage(message);
//how to allow 'updateMessage' from the Task to be executed from here?
}
This already results in "The method updateMessage(String) is undefined...".
How could I make it possible to call the updateMessage outside of the Task itself?
updateMessage() can only be called from within the call() method of a Task. It's a constraint imposed by the design of the Task class.
The missed message updates are due to the fact that there are too many updates and not all of them are forwarded to the event queue. Try to reduce the number of updates or sleep for a little while to separate them out in time

Set up an actitivity that will blocked until a new element insert into my database

I'm new in workflows C #, I want to set up an activity that will be blocked until a new element insert into my database , after I pass to another activity.
From your question I believe you are asking for a way to stop the workflow proceeding until you get a database entry and if you do to continue the workflow.
And if you do not get the entry to not continue the workflow.
This answer uses the Flowchart model of workflows.
A way to do this is to write an Code Activity (also called Custom Activity) that reads your database and determines if the entry has arrived and then sets a bool Out Argument of the activity. This bool should set a Variable in the workflow.
Then after that you add a FlowDecision activity to read the bool Variable.
If true you continue the workflow
If false you add a loop back to your database reading activity.
This solution leaves the workflow running in memory.
There are more sophisticated solutions but as you are new to workflows I have given the most simple.
public sealed class Controller: CodeActivity
{
public OutArgument<String> Item { get; set; }
CodeActivityContext con;
public SqlTableDependency<VacationRequest> _dependency;
private void _dependency_OnChanged(object sender, TableDependency.EventArgs.RecordChangedEventArgs<VacationRequest> even)
{
if (even.ChangeType != ChangeType.None)
{
switch (even.ChangeType)
{
case ChangeType.Update:
try
{
Item.Set(con, "yeééés");// ****Exception
Console.WriteLine("iiiiiiiiiiiiiiii");
//_dependency.Stop();
break;
}
catch (Exception)
{
con.SetValue(Item, "tttt");
break;
}
}
}
}
protected override void Execute(CodeActivityContext context)
{
con = context;
_dependency = new SqlTableDependency<VacationRequest>(ConfigurationManager.ConnectionStrings["DbContext"].ConnectionString, "VacationRequests");
_dependency.OnChanged += _dependency_OnChanged;
_dependency.Start();
//context.SetValue(Item, "test");
}
}

WF 4 OnUnhandledException not hit

I've created a custom activity which contains as a Body another Activity.
[Browsable(false)]
public Activity Body { get; set; }
protected override void Execute(NativeActivityContext context)
{
ActivityInstance res = context.ScheduleActivity(Body, new CompletionCallback(OnExecuteComplete), OnFaulted);
}
private void OnFaulted(NativeActivityFaultContext faultContext, Exception propagatedException, ActivityInstance propagatedFrom)
{
throw new Exception(propagatedException.Message);
}
When an exception is thrown during the execution of the Body, ma handler for the OnFaulted is hit.
My execution starts with a call to static method Run of the WorkflowApplication class. My WorkflowApplication instance has a handler associated for the OnUnhandledException event.
instance.OnUnhandledException +=
delegate(WorkflowApplicationUnhandledExceptionEventArgs args)
{
Console.WriteLine(args.ExceptionSource);
waitEvent.Set();
return UnhandledExceptionAction.Cancel;
};
But regardless of what happens when the Activity hosted in the Body is executed, i never reach the handler defined above. I thought that if i throw an exception from the OnFaulted, i will be able to redirect the flow to the OnUnhandledException but i was wrong. Any ideas ?
I need this in order to centralize my errors, check them and display messages accordingly. Also i need a way to stop the execution and so on and i don't want to define handlers all over the application. Is there any way to accomplish this ?
As Will suggested, i will post what i did to handle my scenario.
Basically, in my custom activity i have hosted an Assign :
[Browsable(false)]
public Activity Body { get; set; }
Activity System.Activities.Presentation.IActivityTemplateFactory.Create(System.Windows.DependencyObject target)
{
return new Assignment()
{
Body = new Assign() { DisplayName = "" }
};
}
I've added this code to my Execute method :
ActivityInstance res = context.ScheduleActivity(Body, new CompletionCallback(OnExecuteComplete), OnFaulted);
I was trying to run this Assignment by giving an array a negative value as index and and an exception was thrown. This, somehow ended my execution but no handler for the events of my WorkflowApplication instance were hit.
Here is the method given as a callback when executing the body ( in our case the Assign activity ) :
private void OnFaulted(NativeActivityFaultContext faultContext, Exception propagatedException, ActivityInstance propagatedFrom)
{
faultContext.HandleFault();
CommunicationExtension ce = faultContext.GetExtension<CommunicationExtension>();
ITextExpression toTextExpression = (propagatedFrom.Activity as Assign).To.Expression as ITextExpression;
string valueTextExpression = string.Empty;
if ((propagatedFrom.Activity as Assign).Value != null)
{
if ((propagatedFrom.Activity as Assign).Value.Expression != null)
valueTextExpression = (propagatedFrom.Activity as Assign).Value.Expression.ToString();
}
if (ce != null)
{
ce.AddData(string.Format("{0} found on Assignment definition [{1} = {2}]", propagatedException.Message, toTextExpression.ExpressionText, valueTextExpression));
}
}
The trick was to call :
faultContext.HandleFault();
and use CommunicationExtension to allow me to to display the erros in the GUI.
The code for this class is trivial :
public class CommunicationExtension
{
public List<string> Messages { get; set; }
public CommunicationExtension()
{
Messages = new List<string>();
}
public void AddData(string message)
{
if (string.IsNullOrEmpty(message))
return;
Messages.Add(message);
}
}
Use this to add the extension:
CommunicationExtension ce = new CommunicationExtension();
instance.Extensions.Add(ce);
where instance is my WorkflowApplication instance.
I understood that for each instance of the workflow application we have one instance of its extension class. So i can send messages like this from all my custom activities in order to display their status.
I hope this scenario can help other people too.

Javafx pass login token from LoginController to CalendarController

I am using Angela's framework for screens management and I am trying to write a very simple Calendar-application. While writing the UI and the controllers and using the aforementioned framework, all screens initialize immediately on program start. This means I have no idea when the user is actually looking at a certain view.
I need the login-token from the server (assigned in the LoginController) to fire a changed value event of some kind in the CalendarController that is currently running in the background (I presume). At the moment I don't know when the Calendar.fxml is visible and/if the user is logged in, and hence I don't know how to structure my logic to make a function start in CalendarController ONLY after the login-token has been set.
Been stuck a few days here, any help would be greatly appreciated. I have tried using an ObservableList and Listlistener-interface to no avail. Here is the respective part of my LoginController. TokenFactory is a class of static fields and methods (mostly trying to debug).
#FXML
public boolean login() throws JSONException, UnirestException {
if(validateUsernameField() && validatePasswordField()) {
HttpResponse<JsonNode> jsonResponse = Unirest.post(TokenFactory.getSERVER_ADR())
.field("username", usernameField.getText())
.field("password", passwordField.getText())
.asJson();
if ( ((String) jsonResponse.getBody().getObject().get("message")).equalsIgnoreCase("OK")) {
String token = ((String) jsonResponse.getBody().getObject().get("token"));
//Ignore JSON to debug
TokenFactory.setToken("fakeToken123");
responseLabel.setText("Logging in...");
myController.setScreen(ScreensFramework.CalendarID);
return true;
} else {
responseLabel.setText("Wrong username or password.");
passwordField.clear();
}
} return false;
}
//Screen management
ScreensController myController;
You have a bunch of options here:
First option: instead of loading all the screens at startup, just load the calendar screen when the login is successful. Then your CalendarController's initialize() method can basically assume the user is logged in.
Second option: modify the framework so that it either returns a reference to the controllers when it loads them, or gives you access to the controllers once loaded. The first version of this would look like:
public <T extends ControlledScreen> T loadScreen(String name, String resource) {
try {
FXMLLoader myLoader = new FXMLLoader(getClass().getResource(resource));
Parent loadScreen = (Parent) myLoader.load();
T myScreenControler = myLoader.getController();
myScreenControler.setScreenParent(this);
addScreen(name, loadScreen);
return myScreenControler ;
} catch (Exception e) {
System.out.println(e.getMessage());
return null;
}
}
Now when you first load the calendar screen, you can get a reference to its controller:
CalendarController calendarController = screensController.loadScreen(...);
so now when you are successfully logged in, you can invoke a method on the calendarController. Note the return type of loadScreen(...) has changed, so you may need to modify other code accordingly.
Alternatively, you could introduce a new map in ScreensController:
public class ScreensController extends StackPane {
private Map<String, Node> screens = new HashMap<>();
private Map<String, ControlledScreen> controllers = new HashMap<>();
// ...
public boolean loadScreen(String name, String resource) {
try {
FXMLLoader myLoader = new FXMLLoader(getClass().getResource(resource));
Parent loadScreen = (Parent) myLoader.load();
ControlledScreen myScreenControler = ((ControlledScreen) myLoader.getController());
myScreenControler.setScreenParent(this);
addScreen(name, loadScreen);
// also save the controller:
controllers.put(name, myScreenControler);
return true;
} catch (Exception e) {
System.out.println(e.getMessage());
return false;
}
}
// ...
// new method to retrieve controller:
public ControlledScreen getController(String name) {
return controllers.get(name);
}
// modify the remove method to clean up the controller as well:
public boolean unloadScreen(String name) {
if (screens.remove(name) == null) {
System.out.println("Screen didn't exist");
return false;
} else {
controllers.remove(name);
return true;
}
}
}
Now when the user logs in, you can do
CalendarController calendarController =
(CalendarController) myController.getController(ScreensFramework.CalendarID);
and invoke whatever method you need on calendarController.
Third option: create a BooleanProperty loggedIn = new SimpleBooleanProperty(); and just set it to true when the user is logged in. Then arrange for your CalendarController to be able to observe it and react when it changes. I like this option less, because arranging for the CalendarController to see the loggedIn property will almost certainly involve some kind of additional coupling between that controller and another class, but it is possible.

commit fragment from onLoadFinished within activity

I have an activity which loads a data list from the server using loader callbacks. I have to list out the data into a fragment which extends
SherlockListFragment
i tried to commit the fragment using
Fragment newFragment = CategoryFragment.newInstance(mStackLevel,categoryList);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.simple_fragment, newFragment).commit();
in onLoadFinished and it gives an IllegalStateException saying
java.lang.IllegalStateException: Can not perform this action inside of onLoadFinished
I have referred the example in actionbar sherlock, but those examples have loaders within the fragments and not the activity.
Can anybody help me with this o that I can fix it without calling the loader from the fragment!
Atlast, I have found a solution to this problem. Create a handle setting an empty message and call that handler onLoadFinished(). The code is similar to this.
#Override
public void onLoadFinished(Loader<List<Station>> arg0, List<Station> arg1) {
// do other actions
handler.sendEmptyMessage(2);
}
In the handler,
private Handler handler = new Handler() { // handler for commiting fragment after data is loaded
#Override
public void handleMessage(Message msg) {
if(msg.what == 2) {
Log.d(TAG, "onload finished : handler called. setting the fragment.");
// commit the fragment
}
}
};
The number of fragments depend on the requirement.
This method can be mainly used in case of stackFragments, where all fragments have different related functions.
As per the Android docs on the onLoadFinished() method:
Note that normally an application is not allowed to commit fragment transactions while in this call, since it can happen after an activity's state is saved. See FragmentManager.openTransaction() for further discussion on this.
https://developer.android.com/reference/android/app/LoaderManager.LoaderCallbacks.html#onLoadFinished(android.content.Loader, D)
(Note: copy/paste that link into your browser... StackOverflow is not handling it well..)
So you simply should never load a fragment in that state. If you really don't want to put the Loader in the Fragment, then you need to initialize the fragment in your onCreate() method of the Activity, and then when onLoadFinished occurs, simply call a method on your fragment.
Some rough pseudo code follows:
public class DummyFragment {
public void setData(Object someObject) {
//do stuff
}
public class DummyActivity extends LoaderCallbacks<Object> {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Fragment newFragment = DummyFragment.newInstance();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.simple_fragment, newFragment).commit();
getSupportLoaderManager.initLoader(0, null, this)
}
// put your other LoaderCallbacks here... onCreateLoader() and onLoaderReset()
public void onLoadFinished(Loader<Object> loader, Object result) {
Fragment f = getSupportLoaderManager.findFragmentById(R.id.simple_fragment);
f.setData(result);
}
Obviously, you'd want to use the right object.. and the right loader, and probably define a useful setData() method to update your fragment. But hopefully this will point you in the right direction.
As #kwazi answered this is a bad user experience to call FragmentTransition.commit() from onLoadFinished(). I have found a solution for this event by using ProgressDialog.
First created ProgressDialog.setOnDismissListener(new listener) for watching the onLoadFinished().
Further i do progressDialog.show() before getLoaderManager().restartLoader().
And eventually place progressDialog.dismiss() in onLoadFinished().
Such approach allow do not bind main UI thread and Loader's thread.
public class FrPersonsListAnswer extends Fragment
implements
LoaderCallbacks<Cursor>{
private ProgressDialog progressDialog;
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_persons_list, container, false);
//prepare progress Dialog
progressDialog = new ProgressDialog(curActivity);
progressDialog.setMessage("Wait...");
progressDialog.setIndeterminate(true);
progressDialog.setOnDismissListener(new OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
//make FragmentTransaction.commit() here;
//but it's recommended to pass control to your Activity
//via an Interface and manage fragments there.
}
});
lv = (ListView) view.findViewById(R.id.lv_out1);
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, final View view,
final int position, long id) {
//START PROGRESS DIALOG HERE
progressDialog.show();
Cursor c = (Cursor) parent.getAdapter().getItem(position);
// create Loader
getLoaderManager().restartLoader(1, null, curFragment);
}
});
return view;
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
switch (loader.getId()) {
case 1:
//dismiss dialog and call progressDialog.onDismiss() listener
progressDialog.dismiss();
break;
default:
break;
}
}

Resources