How to make (and save in RAM) sparsearray at app launch? (android) - java

I am making an android app. There is an activity in the app, which when triggered, makes a sparsearray and fills it with data. Now this process takes upto 1 minute on the emulator, which is very long. So I want to make that sparsearray once, right when the app is launched, and save the sparsearray in RAM for the lifetime of the app. And whenever the activity is triggered it should access the sparsearray in RAM instead of making a new one, thus saving time and processing power. Can this be done, if so how? Sorry if this question is dumb, I am new to android. Thanks!
*Edit: This is what the sparsearray making function looks like:
//function which accesses sparsearray making function
public String[] process(){
InputStream is = context.getAssets().open("feedtitlesandaddresses.txt");
InputStreamReader iz=new InputStreamReader(is);
BufferedReader br = new BufferedReader(iz);
String line = null;
while((line=br.readLine())!=null) {
readLine(line);
}}
//sparsearray making function
private void readLine(String line) {
//some string processing(omitted here)
int num1 = Integer.parseInt(firstNumber);
//int num2 = Integer.parseInt(secondNumber);
if(sparseArray.get(num1) == null) {
sparseArray.put(num1, new SparseArray<String>());
}
temporarySparseArray = sparseArray.get(num1);
for(int w=0;w<size;w++){
temporarySparseArray.put(w, array1[w]);
}
sparseArray.put(num1, temporarySparseArray);
temporarySparseArray = null;
}

You can write you object in the android internal or external file system, and you can read the object when you want to use it.

I feel this question deserves an answer, and I was sure someone would come up with one, but, hmm, not really so far; and if I were Tom Wong, it would currently look to me as if StackOverflow was a place where wannabe experts start fighting over questions rather than answering them. ;) So here we go.
Do something at startup, the result of which lasts as long as your App is in memory: The right place to do this is Application.onCreate(), for which you need to subclass Application. It is okay to store the result in the Application object as well in this case, where you can access it from any Activity by getting the Application context.
Do something that will take some time: In general, it's a good idea to use AsyncTask on Android, but it is specialized for doing things which relate to the User Interface but must not block it. Also, without some explicit tuning, its behaviour will vary amongst different Android versions. Currently, without further measures, if you did your computation via AsyncTask, other AsyncTasks would have to wait first. Also, what you want to do is not a classic task for using an AsyncTask, so use a one-time Thread which simply stores its result finally in a volatile reference.
The following code snippet should give you the idea.
final class MyApplication extends Application {
public volatile String[] expensiveToCompute;
#Override
public void onCreate() {
expensiveToCreate = null;
(new Thread() {
#Override
public void run() {
String[] result = computeMyData();
// it is important to assign the locally created data at once here
expensiveToCompute = result;
}
}).start();
}
}
In this way, expensiveToCompute will be null until the asynchronous computation has finished.
It is important to understand that this Thread will run until it has finished, and that it holds a reference to your MyApplication object. This means that even if the user leaves your app, your Thread will still continue if it has not finished until then.
This is in fact nice, because either Android decides to leave your Application object alive just because it can, in which case the user experience improves. Or Android kills the whole process with the Application object, your Thread and any held data, in which case it will start from scratch next time.
One more thing about, umm, suggestions to move expensive computations into AsyncTask etc: Android assigns a default background priority to such threads, and all background threads will (currently) have to live with 10% CPU time altogether no matter whether the Android system is idle otherwise. So many people who move intensive computations to background tasks notice that it will take ten times longer. Hence, you may want to read my suggestions regarding how to handle this here and/or here.

Related

How to "fire and forget" with kotlin coroutines in a blocking event?

I am making something similar to minecraft plugin, but the API is all in Java.
At some point, there are events. Every event is fired sequentially, and the API will wait until an event finishes before calling the event listener for the next event. These events are called from the main thread, this means that nothing else is running while your event listener code is being run, and the application will crash eventually if you are blocking the main thread for too long.
Basically, I want that when a player is opening an inventory, some first content is sent directly, and some second content is retrieved from a database. In Java, you, would do something like this:
private static final List<Item> firstContent = ...;
public static void onInventoryOpenEvent(Inventory inventory) {
inventory.addItems(firstContent);
forkJoinPool.submit(() -> { // "fire and forget"
List<Item> secondContent = retrieveContentFromDB(); // long and blocking
inventory.addItems(secondContent);
});
}
And in kotlin, some would say to use the GlobalScope, others would say to not use it, but for now I don't see any other way than using it like this:
fun onInventoryOpenEvent(inventory: Inventory) { // not a suspending function
inventory.addItems(firstContent)
GlobalScope.launch {
val secondContent = retrieveContentFromDB() // long and blocking
inventory.addItems(secondContent)
}
}
If you truly want to fire and forget, such that the coroutine will not be cancelled under any circumstance, GlobalScope is the right way to do it. The need to truly fire and forget is rare enough in practice that Kotlin gives you a warning about a "fragile API" if you use it, I think because so many newbies were using it for everything. This was especially a problem on Android (where Kotlin is primarily used), where long running tasks that should run even off-screen should be handled in services instead of coroutines.
But, referring to your example, if inventory is something that could become obsolete and you want to free it to the GC at some point, you should use your own created CoroutineScope that you store in a property, so you can cancel it to clear any running coroutines and prevent them from hanging onto references that should be freed for the GC. If the scope might be used for more than one coroutine, then you should give it a SupervisorJob().
private val coroutineScope = CoroutineScope(SupervisorJob())
fun onEndOfLifecycle() { // some function called when cleaning up memory
coroutineScope.cancel()
}

Why printing all running threads in Java unblocks an application?

I created a GUI Application in JavaFX which communicates with a serial device (I use a jssc connector). When I want to get data I send a communicate, then wait 1s until the wait function terminates. Communicate is also being sent, among other things, when I click one of the buttons (for starting a device, for identification, etc.). During development process I noticed a bug - communication hangs (but only when receiving messages, I still can send one-way communicates for ie. starting a device) when I click too many buttons too fast or I click buttons which send more than one communicate.
Communication is mainly handled by my own class SerialPortDevice. I create an object of a class' type and then invoke particular methods. Here's the method which waits for a message:
private String waitForMessage() throws SerialPortException {
long operationStartTime = System.currentTimeMillis();
long connectionTimeout = SerialPortCommunicationParameters.CONNECTION_TIMEOUT_IN_MILLIS;
String resultMessage = "";
do {
if (readEventOccurred) {
System.out.println();
resultMessage = receiveMessage();
System.out.println("After receiving a message");
messageReceived = true;
}
} while (((System.currentTimeMillis() - operationStartTime) < connectionTimeout) && (!messageReceived));
if (!readEventOccurred) {
resultMessage = NO_RESPONSE;
}
System.out.println("Time elapsed: " + (System.currentTimeMillis() - operationStartTime + "ms"));
return resultMessage;
}
One can notice that message is being received only when a flag readEventOccured is true. It's handled by my implementation of the SerialPortEventListener:
class SerialPortDeviceReader implements SerialPortEventListener {
private SerialPortDevice device;
SerialPortDeviceReader(SerialPortDevice device) {
this.device = device;
}
public void serialEvent(SerialPortEvent event) {
if (event.isRXCHAR()) {
System.out.println("Serial Event Occured!");
device.setReadEventOccurred(true);
}
}
}
readEventOccured is a boolean field in the SerialPortDevice class which contains waitForMessage function. Also, waitForMessage is invoked by another function, singleConversation:
String singleConversation(String testMessage) {
String resultMessage = NO_RESPONSE;
try {
openConnection();
sendMessage(testMessage);
resultMessage = waitForMessage();
closeConnection();
} catch (SerialPortException e) {
e.printStackTrace();
return resultMessage;
}
System.out.println();
readEventOccurred = false;
messageReceived = false;
return resultMessage;
}
... Which is the only function setting readEventOccured to false. And it is a "top level" function in a SerialPortDevice class which handles sending and receiving a communicates to and from a device.
So communication looks like this:
Button click -> Button handler invocation -> device.singleCommunication(buttons_specific_communicate) -> some methods run and then it comes to the waitForMessage -> method waits 1s for the event -> event occurs (everytime - I get the "Serial Event Occured" communicate) -> readEventOccured is being set to true -> if there is some time left (there is always some time left, everything lasts a miliseconds), message is being received in the waitForMessage method.
There is no problem if I click buttons with a short (in a human sense, 2-3s for example) delay or I don't click these which do send more than one communicate inside their handlers. In different situations weird things happen. I still get the message "Serial Event Occured" (so I suppose readEventOccured is also being set to true) but waitForMessage function does not execute
if(readEventOccured)
statement's code. Also, I have to run an application again to be able to communicate with a device (I mean receiving data, sending works perfectly).
What solved my problem was adding "volatile" modifier to the readEventOccured flag (makes sense by the way, things go fast sometimes). But it didn't please me. I wanted to make a code to run correctly without "volatile". My coworker came up with an idea something goes wrong with threads that are being created when I click buttons and invoke communication - maybe something blocks other thing somewhere? First thing I did was to print all the currently runnig threads and... Man, it solved a problem. App was not hanging anymore. Really, I performed "hanging" scenarios 10-20 times with and without
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
System.out.println(threadSet);
at the beginning of the waitForMessage method and result were unambigous - it somehow removed my problem.
I'm almost certainly sure getting and printing threads is not a solution itself. It's something that is being done by the way but I can't find out what is this. Any useful information? Maybe better understanding Threads in Java would help me? Or it is something else?
Cheers
What you're doing is the textbook example of what happens when there are no visibility guarantees. If we distil your code into its essential bits, we get something like this:
boolean flag = false;
void consume() {
while (true) {
if (flag) {
//we received flag, hooray
}
}
}
void produce() {
flag = true;
}
Now, if produce() and consume() run in different threads, there is absolutely no guarantee that consume() will EVER see flag set to true. volatile creates a memory barrier, meaning that all reads/writes of those variable will be fully ordered.
What you also have in the code though, is lots of System.out.println() lines. These complicate the picture, as they themselves are synchronized, and thus create happens-before relationships between different parts of the code. Unfortunately they don't create the correct sequence, but poke in a few more and you can accidentally get it right. The key word here is "accidentally", you shouldn't rely on this behaviour at all.
So marking readEventOccurred as volatile sort of fixes the problem but going a bit further we can see that your waitForMessage() spin-waits, which is rarely a good idea. I would take a look at the CountDownLatch class for example, designed for similar scenarios. (An even better candidate is its close friend, CyclicBarrier.)
What solved my problem was adding "volatile" modifier to the readEventOccured flag (makes sense by the way, things go fast sometimes). But it didn't please me. I wanted to make a code to run correctly without "volatile".
The fact that adding volatile fixes the problem indicates you've run into the lack of guarantees by the Java Memory Model when multiple threads are involved. Simply put there is no guarantee of when a change on one thread is visible on other threads except for specific situations.
The probably reason why printing 'fixes' the problem is the fact that it:
Changes the timing of the program, might mean the situation in which it fails no longer exists.
Temporarily suspends the threads to read out their current state, maybe the JVM also uses that as an opportunity to synchronize memory.
Multithreaded communication is hard, so I recommend you take a look at the classes available in java.util.concurrent, which have guarantees that you might be able to use to solve your problem more elegantly.

"Asynchronous while loop" in JavaFX thread

When I need to do an indeterminate number of pieces of work in the JavaFX thread without blocking the user interface, I use this class
public class AsyncWhile {
private final IntPredicate hook;
private int schedCount = 0;
private boolean terminated = false;
private int callCount = 0;
private static final int schedN = 1;
public AsyncWhile(IntPredicate hook) {
this.hook = hook;
schedule();
}
public void kill(){
terminated = true;
}
private void schedule(){
while(schedCount < schedN){
Platform.runLater(this::poll);
schedCount++;
}
}
private void poll(){
schedCount--;
if(!terminated){
terminated = !hook.test(callCount++);
if(!terminated){
schedule();
}
}
}
}
like this
asyncWhile = new AsyncWhile(i -> {
// return false when you're done
// or true if you want to be called again
});
// can asyncWhile.kill() should we need to
(
If you need a more concrete example, here I'm reading one line at a time from an InputStream and then parsing and displaying a plot parsed from that line:
asyncWhile = new AsyncWhile(i -> {
String line;
try {
if((line = reader.readLine()).startsWith(" Search complete.")){ // it so happens that this reader must be read in the JavaFX thread, because it automatically updates a console window
return false;
} else {
Task<MatchPlot> task = new ParsePlotTask(line);
task.setOnSucceeded(wse -> {
plotConsumer.accept(task.getValue());
// todo update progress bar
});
executorService.submit(task);
return true;
}
} catch (IOException ex) {
new ExceptionDialog(ex).showAndWait();
return false;
}
});
)
Chaining up runLaters like that feels like a hack. What is the proper way to solve this kind of problem? (By "this kind of problem" I mean the problem that would have been solved by a simple while loop, had it not been for the fact that its contents must run in the JavaFX thread without making the UI unresponsive.)
Recommended
In general, basing a solution off of the PartialResultsTask sample from the Task documentation (which relies on Platform.runLater invocations), is the standard way of solving this problem.
Alternate
Rather than scheduling runLater's you could use a BlockingDeque. In your processing task, you perform your time-consuming process just with a normal while loop, generate non-UI model objects which need to be represented in the JavaFX UI, stick those non-UI model objects into your queue. Then you setup a Timeline or AnimationTimer that polls the queue, draining it as necessary and to pick the items off the queue and represent them in the UI.
This approach is similar (but a bit different) to: Most efficient way to log messages to JavaFX TextArea via threads with simple custom logging frameworks.
Using your own queue in this case is not much different from using the implicit queue runLater invocations go on to, though, with your own queue, you might have a little more control over the process if you need that. It's a trade-off though, as it adds a bit more custom code and complexity, so probably just use the recommended PartialResults sample from Task and, if that doesn't fit your needs, then perhaps investigate the alternative custom queue based approach.
Aside
As a side note, you could use the custom logging framework linked earlier to log console messages from multiple threads to be displayed in your UI. That way you don't need to have your reader.readLine call execute I/O on the JavaFX UI, which is not recommended. Instead, have the I/O performed off the JavaFX UI thread and, as you process items, call into the logging framework to log messages that will eventually show up on the UI (the internal mechanisms within the logging framework take care of ensuring that JavaFX threading rules are respected).
Can you see any danger in using my approach?
Sorry for being non-specific here. I'm not going to directly answer this, but tangentially and not always applicably to your approach, using runLater can cause issues, mostly it is not a concern, but some things to consider:
If you send enough runLater calls faster than they can be processed, eventually you will either run out of memory or some runLater calls will start being ignored (depending on how the runLater system works).
Calls to runLater are sequential, not prioritized, so if there are internal events which are also being runLater, such as handling UI events, those might be delayed while your runLater calls are being processed.
runLater offers no guarantee of when later is. If your work is time sensitive, that might be an issue or at least something you need to account for in your implementation.
The runLater system is likely internally fairly complex and you won't know exactly how it is implemented unless you study the source code pretty closely.
Anything that you run on runLater is going to hold up the JavaFX application thread, probably until all of the outstanding runLater calls are complete
Once you have issued a bunch of runLater calls, you can't easily intersperse their processing over multiple pulses in the JavaFX animation system, they will likely all be executed on the next pulse. So you have to be careful not to send too many calls at once.
Those are just some things that come to mind.
In general though, runLater is a sound mechanism for many tasks and a core part of the JavaFX architecture. For most things the above considerations don't really have any consequence.
Writing quality multi-threaded code is pretty tricky. To the point where it often best avoided where possible, which is what the JavaFX system attempts to do for the most part by making scene graph access single-threaded. If you must do it, then stick to the patterns outlined in the Task documentation or utilizing some of the high level java.util.concurrent systems as much as possible rather than implementing your own systems. Also note that reading multi-threaded code is even trickier than writing it, so make sure what you do is clear to the next person.

multiple calls to GCE within 1 AsyncTask

I'm a little new to AsynTasks in java programming for Android...
But, I see their point (let the UI continue while slow operations happen)
I have a GCE (Google Cloud Endpoint) API set up. To access it from the android app, it must be executed in an AsynTask according to what I've read.
My confusion lies with exactly what is the limitation within the AsyncTask before returning to onPostExecute?
The obvious use, is calling your API once.
So something like:
final myAPI.Builder builder = newmyAPI.Builder(
AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), null);
builder.setApplicationName("mine");
AsyncTask<String, Void, com.appspot.myapp.myAPI.model.sample> publishAPItask =
new AsyncTask<String, Void, com.appspot.myapp.myAPI.model.sample> () {
#Override
protected com.appspot.myapp.myAPI.model.sample doInBackground(String... strings) {
// Retrieve service handle.
myAPI apiServiceHandle = CloudEndpointUtils.updateBuilder(builder).build();
try {
myMethod myMethodCommand = apiServiceHandle.sample().myMethod();
newthing.setthing(myMethodCommand.execute().getthing());
...
that last line executes, but also refers to the result already. I've read thats a no-no. Is that true? From here is a quote:
If you need to use an object that should be returned by the task, make use of the task’s onPostExecute override method. If you request a Lobster object from your API using an AsyncTask, and >then immediately try to use it in your next line of code (for example, Lobster lobster = new GetLobsterAsyncTask().execute(lobsterName); lobster.dance();), you will receive an exception. So, not only will your lobster “not dance,” it will “throw a NullPointerException at you”.
But it's a bit open to interpretation. Since I've never had an issue with the above use of the result, right away.
I seem to get intermittent issues when I added another call after the above code, calling other GCE methods within the same AsynTask - note, not using the result of the other calls.
myMethod2 meMethod2Command = apiServiceHandle.sample().myMethod2();
newthing2.setthing(myMethod2Command.execute().getthing());
So is there a hard rule somewhere that says we can only make 1 call to GCE methods per AsynTask?
Are the lines within the AsyncTask doInBackground() executed in sequence, or is it possible these GCE .execute() calls are made in parallel?
Before I rewrite a couple AsyncTasks so that they only contain 1 call each (and have a long line of onPostExecute() stacked up), I'd like to make sure I understand it...
It gets complex for me as I have a bunch of calls to make even a loop of calls. I want to make to my GCE method. So second question is: Any suggestions for making a loop of calls to GCE methods? I've also read the AsynTask can only executed once.
UPDATE: I have now just gone with the assumption that we can only make 1 GCE call per Asynctask. This makes for some interesting challenges for me, as I need to make a few in a certain circumstance in my app.
Anyway, what it turns out to be for me, is a loop of asynctasks being called, where each asynctask being called, ends up calling another loop of asynctasks within their onPostExecute.
ie. psuedocode:
loop
asynctask 1 defined {
do inbackground {
...;
}
onPostExecute {
loop
asynctask 2 defined {
doinbackground {
...;
};
onPostExecute {
};
};
asynctask2.execute;
end loop;
};
};
asynctask1.execute;
end loop;
And the real challenge now, is that I need to know when they've all completed, before doing another operation.
I've seen a couple suggestions for an array of tasks and checking their status, or calling a function to increment a count.
Let me know if you have other ideas...
--- final update
Ended up going with a thread tracker count. Before each execute above, I increment 1. In each postexecute, I decremented 1. When the tracker's count is 0, I know I can call the final operation needed.
private class threadtracker {
public int todo;
public threadtracker (String grpid) {
todo = 0;
}
public void add(int adder) {
todo = todo + adder;
Log.v(TAG, " threads:" + todo);
}
public void subtract(int subber) {
todo = todo - subber;
Log.v(TAG, " threads:" + todo);
if (todo == 0) {
//do final operation
}
}
}
(Edit: I've edited my answer based on nempoBu4's comment)
Here's some info on AppEngine Endpoints and using Endpoints in a Android client:
Udacity has a course covering App Engine it might be worth some of your time.
https://www.udacity.com/course/ud859
You should read their Android client code though and see how they consume Endpoint methods in the client. It's on GitHub. The app is called Conference Central.
https://github.com/udacity/conference-central-android-app
So is there a hard rule somewhere that says we can only make 1 call to GCE methods per AsynTask?
I don't think so, I've made multiple calls to my backend from a background thread using endpoints with no problems. The only thing I would worry about doing this in a single AsyncTask, is the amount of time it would take to complete. "AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.)" As per the Android Reference on AsyncTask.
Any suggestions for making a loop of calls to GCE methods?
I've set up an IntentService to consume endpoint methods in a background thread. It's pretty straight forward to use, just follow the developers guide. It'll put calls to the service in a queue, then once the service empties the queue it'll shut its self down. You can set up a Broadcast manager to handle results.
Good luck.

Do I need to copy static objects if I want to access them from an AsyncTask?

I have a project that uses AsyncTask to get work done in background.
This project also uses a class as a generic holder for static values like database keys, but also for one or two useful objects for the whole project. Let's say this class is called public class Constants.
I want to access one of these objects from an AsyncTask, and I don't know if I need to copy it or not.
I am not actually getting errors or crashes, but I get some user feedback reporting crashes that I cannot reproduce, so I'm gessing I am doing something wrong with this.
My current processing is this:
onStart() {// somewhere in the UI thread
new MyTask(Constants.theObject).execute(); // (1)
}
// ...
class MyTask extends AsyncTask<...> {
MyObjectType object;
MyTask(MyObjectType theObjectInstance) {
object = theObjectInstance; // (2)
// ...
doInBackground() { // (3)
// ...
}
In (1), Constants.theObject is a static object created at application startup
In (2), I get a reference to the existing static object Constants.theObject
In (3), we are no longer in the UI thread, and I want to access Constants.theObject (which may also be being used in the main thread)
.
I think there are three possible cases.
this code is ugly, I should do otherwise
this code is OK, the user feedback is not about this
this code is quite OK, but I should make a copy of Constants.theObject if I want to use it in doInBackground; otherwise it can fail
I hope you can help me! Thanks a lot for reading.
From what you've written, I don't think you need to make a copy, unless MyObjectType is NOT thread-safe, in which case, you need to ensure that only 1 thread at a time is modifying it/it's-non-thread-safe-methods. (Making a copy would indeed solve this, but if you can make a copy, is a global-static really what you should be using anyway?)
Are you 100% sure that 1 and 3 can only happen AFTER the object has been initialized?
It may be because more than one thread is trying to change the same object. it may cause unexpected results/complete failure. You may wanna use some lock so that no 2 threads can updates the object at the same time. This case it will slow down your asynch operations as they all depend on exact one intance. I guess you are using static object for a reason, you may want to consider it doing some other way if possible.

Categories