How to fix dropped frames from a slow database connection? - java

button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
progressBar.setVisibility(View.VISIBLE);
button2 = (Button) findViewById(R.id.button);
button2.setVisibility(View.GONE);
Log.d("email", email);
email = emailView.getText().toString();
Log.d("email2", email);
password = passwordView.getText().toString();
connection.start();
try {
connection.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d("00", "00");
Log.d("11", "11");
if (!validate()) {
onFailed();
clearForm((ViewGroup) findViewById(R.id.lin));
progressBar.setVisibility(View.INVISIBLE);
button2.setVisibility(View.VISIBLE);
} else {
screenSize();
}
}
});
}
I have an android app that I have been making for work which makes two calls to two different databases. One database is on site and is our and is super fast while the other connection is to an old database system off site. I have used Async and now I am using java threads (I find them easier to work with and alot more useful). I just want to know if there is a way to stop these dropped frames when connecting to the database when the user logs in because this creates a lag in when the log in button is submitted and then skips the progress spinner. The lag is around 2 second and normally drops around 300 frames.

I'm guessing that connection in the following is a Thread.
connection.start();
try {
connection.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
If so, then the problem is clear. When you call join() you block the UI thread. That is what causes the "lagging". If you want to avoid lagging and frame loss, you must not cause the UI thread to block.
The solution is something like this:
The listener should launch the thread (or whatever), put the UI into a "waiting to validate" state, and return.
The thread should establish the database connection, validate the credentials, then use runOnUiThread to take the UI out of the "waiting to validate" state.
If the user clicks the button while in "waiting to validate", ignore it.
The background thread could update the UI to indicate progress. And there needs to be some indication to the user that the validation step has passed or failed.

Related

Android java - Trying to show snackbar in new thread

Ive been trying to make my bluetooth connection thread be able to send messages to the user through snackbars, but they never appear on the screen.
In main method:
//listener for connect button
try {
Button btn_connect = findViewById(R.id.btn_connect);
btn_connect.setOnClickListener(view -> {
if(bluetoothService.isStarted()){
snackbarMsg(findViewById(R.id.btn_connect), "Bluetooth connection already established");
} else{
new Thread(() -> {
try {
Log.i(TAG, "New thread started");
bluetoothService.run(MainActivity.this);
Log.i(TAG,"Bluetooth service started");
snackbarMsg(findViewById(R.id.btn_connect), "Bluetooth service started");
} catch (Exception e) {
Log.e(TAG, "Bluetooth service failed", e);
}
}).start();
}
});
} catch (Exception exception){
Log.e(TAG, "Bluetooth service failed");
}
in BluetoothService class:
public void snackbarMsg (View view, String msg){
try {
Snackbar snackbar = Snackbar.make(view, msg, BaseTransientBottomBar.LENGTH_SHORT);
snackbar.show();
} catch (Exception exception){
Log.e(TAG, "Could not show snackbar", exception);
}
}
The view i send with the method is always of something on the main screen, so for example using "snackbarMsg(findViewById(R.id.button_send),"Failed to find bluetooth server");"
where button_send is on the screen i want to show the snackbar.
ive tried using runnables and extends thread and whatnot. But since i already have extensions on bluetoothservice class that didnt work, and runnable proved troublesome because i need to send context when starting the run method, and that context seemingly cant be sent at an earlier state, meaning i cant send that info when i create and object fom bluetoothservice at the beginning of the program.
Secondly: im not sure i even need a second thread, since my bluetooth connection is only sending data, not receiving, am i just doing useless work?
You need to run it on the UI/Main thread.
Use runOnUiThread(action: Runnable)
runOnUiThread(() -> snackbarMsg(view, "insert message"));

Android application is hanged and showing black screen for 5-6 seconds when checking if a server port is open or not using ThreadPoolExecutor

I need to run a service if a server port is open. I am doing this by using below method.
public Future<Boolean> ifPortIsOpenThenStartIridiumService(final Context context, final String device_mac, final String device_imei, final String input_mobile) {
return Executors.newFixedThreadPool(20).submit(new Callable<Boolean>() {
#Override
public Boolean call() {
try {
String SERVER_IP = "IP Address";
int SERVER_PORT = Server_port;
int DURATION = 1000;
Socket socket = new Socket();
socket.connect(new InetSocketAddress(SERVER_IP, SERVER_PORT), DURATION);
socket.close();
Log.d(TAG, "Port is Open");
runIridiumService(context, device_mac, device_imei, input_mobile);
return true;
} catch (Exception ex) {
Log.d(TAG, "Port is not Open");
CustomToast.showToast(context, "No Internet Access.", "If in flight, please switch to \"Aeroplane Mode\" and connect to the airline's Wi-Fi network.", 1);
return false;
}
}
});
}
Above code is working but when I run this method the application is getting hanged and black screen is shown for 5-6 seconds.
I found below message on Logcat.
W/ActivityManager: Launch timeout has expired, giving up wake lock!
After that service is started and application is working well. How can I get rid of this problem?
Thanks in advance.
After some study, as far as I understood,
Android application is hanged and showing black screen for 5-6 seconds Because,
Future -
A Future represents the result of an asynchronous computation. Methods are provided to check if the computation is complete, to wait for its completion, and to retrieve the result of the computation.
So, it waits until operation is finished. You can get more info from here.
newFixedThreadPool -
At any point, at most nThreads threads will be active processing tasks. If additional tasks are submitted when all threads are active, they will wait in the queue until a thread is available.
Get more info from here.
The possible solution of your problem is to use ScheduledExecutorService.
Before that you can check Future is completed or not using
if (YOUR_FUTURE.isDone()){
result = (String) YOUR_FUTURE.get();
}
to avoid unwanted or extra loop.

Spring Statemachine timeout and persistence conflict

I have noticed an issue in using timeouts and redis persistence with statemachinefactory.
Above is my uml diagram for the state machine. I have added a stateListener in my code and every time its persisted.
StateMachine stateMachine = factory.getStateMachine();
stateMachine.addStateListener(new CompositeStateMachineListener<String, String>() {
#Override
public void stateContext(StateContext<String, String> arg0) {
String user = (String) arg0.getExtendedState().getVariables().get("imei");
if (user == null) {
return;
}
log.info(arg0.getStage().toString() + "**********" + stateMachine.getState());
try {
redisStateMachinePersister.persist(arg0.getStateMachine(), "testprefixSw:" + user);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
});
Note : ExitPointGQ points to a initial state called WAITFORCOMMAND of the parent machine.
Now taking the scenario where I need to wait by giving the signal WAIT, the machine goes back to WaitForGenQueryRes which is right. But by now, the first timer has started and after 60 seconds, the timer fires and exits through the exit point and persists that the state is now at WAITFORCOMMAND whereas it has to be at WaitForGenQueryRes because I looped it.
Please point out my mistake so I could fix this.

JavaMail : FolderClosedException coming frequently

I'm using java mail to connect with gmail and I'm keeping one store for the all actions. (Store is set to static.).
And the IMAPFolder instances are attached with imap listeners. So the folders are kept always open. (Folder close is not called any time) But while running after few minutes I'm getting FolderClosedException. After that exception, though the folder can be reopened but the idle() command cannot be issued again, which will result in NullPointerException.
Is there any wrong with keeping folders open always?
Thanks in advance.
===================================================================
[Edit]
Here I'm pasting the actual code i'm doing POC with. The NullPointerException comes when I check .isConnected() after reconnecting the store. Below is the run method of Thread which sends idle() command to the store.
public void run() {
while (true) {
try {
System.out.println("Checking connectivity...");
if (store.isConnected()) {
store.idle();
System.out.println("IDLE send...");
} else {
Thread.sleep(5000);
System.out.println("Tring to connect...");
//Trying to reconnect to the store.
store.connect();
System.out.println("Previous store connected again");
}
} catch (InterruptedException ex) {
System.out.println("InterruptedException...");
} catch (StoreClosedException ex) {
System.out.println("StoreClosedException...");
} catch (MessagingException ex) {
System.out.println("MessagingException...");
}
}
}
Here is the stack trace:
Exception in thread "Thread-1" java.lang.NullPointerException
at com.sun.mail.imap.IMAPStore.waitIfIdle(IMAPStore.java:1881)
at com.sun.mail.imap.IMAPStore.getStoreProtocol(IMAPStore.java:946)
at com.sun.mail.imap.IMAPStore.isConnected(IMAPStore.java:1347)
at pocworks.POCWorks1$IDLEThread.run(POCWorks1.java:125)
Generally, mail servers don't like you to keep connections open when you're not using them. Typical IMAP servers will give you 30 minutes before they time out an unused connection; Gmail may be more aggressive.

Passively listening on a socket for a chat application

I am currently developing a chat application which is quite basic overall, however I am encountering problems when receiving strings from both the client and the server side. I am using a thread to passively listen on the socket for incoming messages, which is where I suspect the problem to be. Am I doing this the right way?
Source:
Code for sending strings:
send.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
messageBuffer = message.getText();
out.println(messageBuffer);
chat.append(username + ": " + messageBuffer + "\n");
message.setText("");
}
});
I then have this which passively listens (problem is probably here):
public void run(){
while(true){
try {
messageBufferIn = in.readLine();
System.out.println(in.readLine());
chat.append(recipient + ": " + messageBufferIn + "\n");
} catch (IOException e) {
e.printStackTrace();
}
}
}
Im also calling the thread using this:
public static void startChatting(){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
Thanks for any help you can provide, Im still new to threads overall so my mistake might be quite mediocre.
Edit: The problem is when I try sending a message to the receiver, nothing comes through, I can confirm that they are connected. In fact the System.out.println(in.readLine()); doesnt come through at all, not even a "null" output.
you have got issue with Concurency in Swing, Swing GUI don't know that you running / open the Socket on Background Task,
all updates to the Swing GUI must be done on EDT, otherwise nothing happened or you got a few exceptions
have to wrap all updates from Background Task (in your case Runnable#Thread) to the invokeLater for Swing GUI
while(true){ is endless loop put there Boolean variable instead of true, then you can to stop, start or restart whatever in your case Socket
in the case that send.addActionListener(new ActionListener(){ runs only once time (if user invoked by JButtons click) then to use SwingWoker for opening Socket, SwingWorker quite good guarantee that all output should be done on EDT
difference betweens Runnable#Thread and SwingWorker is that SwingWorker is designated to run only once times
I suspect your main problem is that you're not flushing the OutputStream. You'll want to add out.flush() after you've finished writing to it and want to send the message. For example, your ActionListener would look like this:
send.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
messageBuffer = message.getText();
out.println(messageBuffer);
out.flush();
chat.append(username + ": " + messageBuffer + "\n");
message.setText("");
}
});
If you don't do this, your OutputStream will sit there until it's buffer's full (which will be a lot of messages).

Categories