I'm more used to procedural programming and what I've done basically works but when I look at it I think it can't be very efficient and there must be a much better way of doing the same thing. Could someone show me what it is? At the root of this is how to load different views from main.java and dispose of them based on the contents of a database.
I am building a database application with a Java Interface, using JDBC. I want to be able to load 3 different GUIs for 3 different users, depending on which one logs on. My initial stab at this is to build a java bean class for each table in the database and corresponding Manager classes to deal with interacting with the database. At the user end of things, I load a login window for them to attempt to access the database. When the user enters their correct login details, these are saved to a Singleton class named Session.java for reference while they're using the program, so that I don't have to go back and forth to the database to check for their information. The Singleton class is then used to determine the appropriate interface to load for them. I was doing this from Main.java like this:
LoginScreen login = new LoginScreen();
JohnsView john = new JohnsView();
MarysView mary = new MarysView();
PaulsView paul = new PaulsView();
login.setVisible(true);
login.setLocationRelativeTo(null);
//while the user has not completed login hide their database interface screen
while (!Session.isLoginSucessful()) {
john.setVisible(false);
mary.setVisible(false);
paul.setVisible(false);
}
when the user enters their login details via the GUI I check if their user name and password matches an entry in the database. If it does I set the variables in the Singleton class named Session.java like
this:
Session.setTheUserID(user.getIduser());
Session.setTheUserName(user.getUserName());
Session.setTheUserPassword(user.getPassword());
Session.setTheUserLevel(user.getUserLevel());
Session.setTheUserStaffID(user.getStaffID());
Session.setLoginSucessful(true);
then back in main.java I use a switch statement to .dispose() of the unneeded views and make the appropriate one visible like this:
//dispose of login once it's finished with
login.dispose();
//get the user 'level (1,2 or 3) from the singleton class...
int usrLev = Session.getTheUserLevel();
//check their level with the switch statement for the appropriate view to load
switch(usrLev) {
case 1:
john.setVisible(true);
mary.dispose();
peter.dispose();
break;
case 2:
mary.setVisible(true);
john.dispose();
peter.dispose();
break;
case 3:
peter.setVisible(true);
mary.dispose();
peter.dispose();
break;
default:
break;
}
I know I could approach this problem differently and put the login box into a bigger Jframe and manipulate the contents of the Jframe based on who logs on. I've looked at some examples of this in answer to other questions on here, but this wouldn't achieve what I want it to. I want to be able to load different views from Main depending on variables derived from the database. Do I need some kind of view manager class that's called from main? I've tried this a few times but end up deleting it because it doesn't make sense when I try it. I can't seem to figure this out in java. Any help with understanding this and answering it is appreciated.
OK. I solved this. Though rather than delete the post, I thought I'd leave it here for anyone else who is more used to procedural programming than OOP.
Basically nothing happens in Main apart from launching the first window of the application. In my case a login screen. Many people delete main, but I found it useful to keep it as I may want to do some multi-threading to handle communications with the database in the future, if I push the database onto a server rather than have it on my local machine.
Basically the code in the 3rd block above goes in the GUI code, inside the button action method that handles button presses for logging on. In that method you listen for input from the user, check if it matches what's in your database. If It doesn't tell them so through some visual feedback. If it does allow the code to progress to block three above, whereupon you load the view you want and call this.dispose() on the current view.
I'll leave this for a bit. if its not a useful contribution, I'll delete it.
Related
I've been searching the internet and stackoverflow for several hours for a solution to my question.
To the current problem:
I have a interface which makes it easier for the user to edit a SQLite database.
In my main interface the user has the possibility to set a filter for the display of the data with the help of several combo boxes.
If a new record is to be created, I open a new interface which allows the user to generate the data by just a few entries.
For this, I first close the main interface and then call the create interface.
However, if the user wants to cancel the creation process, the main interface should be loaded again with the previously made selection options and the create inteface should close.
Unfortunately I do not know how to achieve this.
I tried to accomplish this by imitating the last input of the user in the main interface initialize attempt. However, this is not possible because several combo boxes are required for the user selection and react completely dynamically to the previous selection.
I´m glad for every comment or helpfull link
I'm a just diving head first into Android Studio and am working on my first app which is a sort of surfing log application. Basically it is to keep track of various weather conditions each time the user goes out surfing.
I have created a Java class "Session" with the following fields:
Date (Date)
Location (String)
Tide height (float)
Surf size (float)
more to come, keeping it simple for now.
My application will flow as follows:
There will be a Main home screen activity, with buttons, and also a small tableview that displays your 3 most recent sessions.
Buttons including:
New Session: this takes you to a new activity with various text inputs for each of the above fields, a date selector... and a save button.
My Sessions: this will take you to a tableview where you can view all of your past sessions. You can organize them by location, date, surf size...
Thus my question:
What is the best practice to pass all this data between the various activities?
To me the most obvious way to go about this is to have a central ArrayList that gets loaded in the main activity and then this gets somehow passed around to all of the subsequent activities. It contains all the sessions that you have ever created.
So lets say I tap the "new session" button on the main screen. This takes me to the new Session activity. I enter all the fields and hit save. I would like to take this data, create a new session object and then add this to the array back in Main Activity. So far my research tells me to pass all this data back using a bundle and the intent.putextra() technique. However it seems cumbersome. Is there not a better approach where I could just create a new object of my Session class and then append it to the central array?
Again let's say I tap the 'my sessions' button from the main activity. I would like this to load up a new activity which is a tableview that allows the user to scroll through all of their previously created sessions and tap on one to view the details.
I've done a bit of research and it seems there are various ways of going about this, I've read up a bit on Singletons, I've looked into creating some sort of static class that I could then reference from multiple activities, I've read about parcelable and serializable...
Perhaps though someone with some android experience could shed some light on the most efficient and standard way of accomplishing what I would like to do.
Again I want to reiterate that this Array or collection of "Sessions" is going to be the center of the app. Pretty much every activity I implement down the road is going to be using this data in someway or another. Whether it's displaying it a tableview which can be sorted in different ways, to running statistical analysis on it, to displaying pins on a map of each location...
I think you want to keep your data in a database and use a pub/sub workflow to keep track of it.
For example, you can use Firebase. Everytime a part of your application does an update (even a different user on a different device) any other part of your code can listen to that change and capture it.
Firebase is just an example, RethinkDB, MongoDB all have this option.
It is not a good option to use a data structure that is on your app: it will become really messy if it needs to be shared between different parts of your app, and impossible if you need other users to be aware of the change.
I think you should go for an event-based library like RxJava2. you can easily subscribe to a bus (subject) which emits all data created up till now.to keep other app's components up-to-date.
for you specefic use case. there is sth great in RXjava2 is called Replay Subject
Replay Subject:
It emits all the items of the source Observable, regardless of when the subscriber subscribes
a simple implementation would look like
public class RxReplayBus {
private static ReplaySubject<Object> subject = ReplaySubject.create();
private RxReplayBus() {
// hidden constructor
}
public static Disposable subscribe(#NonNull Consumer<Object> action) {
return subject.subscribe(action);
}
public static void publish(#NonNull Object message) {
subject.onNext(message);
}
}
from your component subscribe :
disposable = RxReplayBus.subscribe(new Consumer<Object>() {
#Override
public void accept(Object o) throws Exception {
}
});
and unsubscribe using :
disposable.dispose();
i am trying to define a default webdriver state.
This state of the webdriver is after a log-in and create script, which take care of accessing the website and creating a new workspace where i wish to continue testing from. I am trying to build the rest of the classes from this starting point.
Returning this driver and executing the next command works, but after i executed the first action in the workspace, i cant return to the desired default state so i can call on other individual classes with different functions on the site.
login script : new firefox driver, geturl, fill in info,click on confirm, return driver
create workspace: login script, continued with nagivagtion between menus and filling in workspace info, and creating it, and returning it.
code is long, wont paste it here.
My problem is that after creating a workspace and starting further actions, every time a new action is called, selenium goes through with all the login stuff and creation again.
I am not a very experienced coder, so i am asking for help.
Is there i way i could define a public variable that can hold this state of the driver ?
How can i revert to this state after executing actions?
i am currently assigning WebDriver driver = logInAndCreate() at the first line of each action, which obviously deals with that 2, and i end it in return driver;
msot of the actions i defined already on the site are few lines of code handling navigation, finding and acting on webelements and such. there are tons of options and writing self standing test case for all is not going to happen, so i decided to arrange actions into classes and build my cases from these parts.
There is no state with WebDriver, it's just a connection to a browser that you can use to send commands to the browser. Because of this, you can't revert the state of the site using WebDriver. Also, having a function return driver accomplishes nothing either because you aren't changing the state of the driver inside the function.
Probably your best bet is to get with your devs and see if there's a way you can create a cookie, etc. that contains state. For example, maybe once you log in with a user, a site cookie is created to indicate that a user is logged in. Rather than using the UI to log in, you could create the properly formatted cookie that puts the site in the state of a logged in user. That's just an example but that should be enough to get you started.
I am currently making an android app for a friend who is a photographer where he will display his images in a RecyclerView. We would like to have sort of like a "like" feature where they can like his pictures. My question is, how would I keep track of the "likes"? What I mean is, how can I make it so that if someone already liked it, they cannot exit the app, come back and like it again? I thought about adding a +1 every time there was a like to the image properties in a database, but how can I keep them from exiting the app, coming back, and liking it again? TIA!
your problem is just a matter of identity. To achieve your goal, you should have a way to identify every piece of the pictures and each of the person who will give up-votes to these pictures.
If you can identify different pictures and different users, you can achieve your goal by either of the following ways:
For each of the pictures store all the users that have liked it. And every time a user want to like a picture, you should check whether he is in this collection or not. Only add the identity of the user to this collection if he is not in this set which means he did not like this picture before
Or you can store all the pictures that are liked by the user.
Which way is better depends on your other use cases.
To identify your pictures you can just assign a distinct name for each of the picture.
So you can see the key problem it how to identify your users.
Since you do not provide a detailed use case of the like action, I will describe some general ideas.
If you have a server
If the user must login, you can identify your users by their login id
If your user do not need to login, you can use some other information to identify your user for example their device id, MAC address or other device-specific indentity.
If you do not have a server, then how can you identify all the users that use the same device? The only way I can come up with is that, you must implement a local user system and ask the user to log in before they want to like a photo.
If you have so signing in users my guess is that you can't. You could save on a hidden file on the device the ids of the photos the device "liked" but this can be easily deleted if the user deletes the apps cache files or uninstall/reinstall.
Not an android expert here, just mho
With login:
In your Database there are "User", "Image" and "User_like_image"
You just have to check if this user didnt already upvoted the image
without login:
You locally store the ID of every images he upvoted
A rough idea: with each item that can be liked store a list of ids that liked it on the server. Your like count is equals to the list length.
On each device generate a random device id token (UUID.randomUUID() is always a good candidate), persist it locally on the device (e.g. in SharedPreferences - wiping the app data will kill it but that can't be solved reliably) and send it to the server with each request.
The server can now
tell you whether you already liked an image which is nice to see on the device and
reject multiple likes from the same device
A simpler approach: store locally in e.g. SharedPreferences that you liked the item. Then behave nicely and don't send another like request to your server backend when you see that you already did. Can be abused because it relies no the client software to be nice but I doubt a small photographer app needs to care too much about that.
A more elaborate approach: require user accounts. That works accross devices and persists through app uninstalls. People that go far enough to create multiple accounts to vote multiple times can't be stopped anyways. The big downside is that people will most likely not want to have another account just to like some photos. Would not recommend if avoidable.
What I did to avoid having people like the same item twice was:
Have 2 states with the same button. If you clicked on "like" the button state changes to "Remove Like" Save the state of the button in shared prefs and check the state before a click is given.
Example:
button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
String ButtonText = button.getText().toString();
if(ButtonText.equals("Like"){
//code for Like
button.setText("Remove Like");
}
else{
//code for remove Like
button.setText("Like");
}
}
});
I have created a an application for a project - it's very basic... what I would like to do next is see how users are using my application e.g. buttons pressed, which page is viewed the most, for how long etc.
I am new to java and I do not understand how I can implement such thing; I have an idea but do not know whether it is efficient;
I would add a counter for each of the buttons in my app, whenever a button is pressed the counter increases by 1 and so on and so forth;
To see how long a user stays on a page, I could add a timer when the user enters the page, timer starts and stops when user exits.
...
Would something like this is viable and efficient? are there better ways of implementing such algorithm.
Not sure if there are, I searched but couldn't find any, does google offer such service like they do for websites with google analytic.
I am sorry, I've no to show this, as I haven't actually starting doing it. Wanted to get a grasp of it before I do and find out whether it is the correct strategy.
I would really appreciate your help.
https://developers.google.com/analytics/devguides/collection/android/v4/
Analytics for android apps maybe its what u are looking for
Start here: http://www.google.com/analytics/mobile/
https://developers.google.com/analytics/devguides/collection/android/v4/
You could also go with that you stated already, and add those values to an array. Just note that this will require you to turn on some permissions which might make your app unpalatable for some individuals.