Starting an Activity from Runnable() - java

Hopefully not a dupe, dug around as best I could and came up with nothing. All the suggestions in SO when I typed the title had less than 0 upvotes, so hopefully I'm not following the same path. My question, essentially, is what will happen if I do this on my main thread:
new Thread(new Runnable() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
startActivity(i);
}
});
}
}).start();
Assuming i is an intent, that I didn't screw anything else up, etc. Obviously this is a very trivial case. But I'm wondering if there's anything I need to do to/on the worker thread? Am I going to cause a memory leak or other issue if I do this? Do I need to make a call to something on the worker thread to tell it that I no longer need it? Will it understand on its own that it's no longer needed? Am I just completely misunderstanding something? Thanks!

Well I am not sure if that is going to work. But if you will go this way you might get memory leaks.
You can achieve activity creation posting an event from asynctask https://github.com/greenrobot/EventBus
, and subscribing to that event in your activities/fragments. You can create base class for multiple activities and subscribing inside it. So you will get event anywhere.

A java Thread will become Dead after finishing execution. You will have a short memory leak until the thread finishes it's task (because the thread is bound to the current activity and that activity is not destroyed until you finish your stuff).
Anyway I would suggest you to use AsynkTask if you want to update the ui after some background task.
If you are more advanced the best solution would be to use RxJava or Live Data. In android we don't use Thread too often since we have other wrappers that ease our communication between threads

Related

What's proper way to make my own events in java

I'm student and I'm working on project with few of my friends. My task is to make something like class library. Classes in this library should provide API for my friend who must make GUI part of application. GUI could be made by any toolkit (Swing, JavaFX, SWT, AWT, all should work, in fact, it should work even if there is no GUI). I need to make class that waits for data to arrive from network. I don't know when data will arrive, and UI must be responsive during waiting, so I put that in different thread. Now problem is how to make GUI respond when data arrive. Well, I tought that this is asynchronous event and GUI should register event handlers, and I should call that methods when event happens. I proposed this solution:
interface DataArrivedListener{
void dataArrived(String data);
}
class Waiter{
private DataArrivedListener dal;
public void setDataArrivedListener(DataArrivedListener dal){
this.dal = dal;
}
void someMethodThatWaitsForData(){
// some code goes here
data = bufRdr.readLine();
//now goes important line:
dal.dataArrived(data);
// other code goes here
}
}
My question is:
Should I replace "important" line with something like this:
java.awt.EventQueue.invokeLater(new Runnable(){
#Override
public void run(){
dal.dataArrived(data);
}
});
Or something like:
javafx.Platform.runLater(new Runnable(){
#Override
public void run(){
dal.dataArrived(data);
}
});
Or maybe I should do something completely different?
Problem is that I'm not sure which of this will work for any type of UI. If it's GUI, dataArrived() could potentialy make changes to GUI and no matter what type of GUI it is, this changes should be drawn on screen properly. I also think that it is better if I do "invoke this code later" so that my someMethodThatWaitsForData() method could trigger event and continue on with it's on work.
I appreciate your help.
Here's an Event Listener article I wrote a while back. The article explains how you write your own event listeners.
You're correct in that you want to write your own event listeners if you want your library to work with any GUI.
I'm most familiar with Swing, so yes, you'll have GUI code that looks like this:
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent event){
dal.buttonPressed(data);
}
});
If you want it to be completely agnostic to what GUI is being used the only real solution is to let the receiver handle it in dataArrived. Since every toolkit has its own implementation all you can really do to make it work with any toolkit is to disregard it. Otherwise what you will actually end up with is a list of "supported toolkits" and a case for each one.
If you just want dataArrived to be executed away from someMethodThatWaitsForData then you could make your own dispatch thread or make a new thread each time.
If you want to be truly independent of any front-end system, I would recommend creating two threads. The first is your Waiter, which will just listen for events and put them into a Queue of some sort (see the "All Known Implementing Classes" section). The second will invoke the data listener or listeners whenever the queue is not empty.
The concept of invoking a Runnable in the background is kind of deprecated since the invention of the concurrent package. The main reason that this was done in earlier days, is that the GUI code needs to be executed in a different thread, to guarantee that it stays responsive, even if the main thread is busy doing some calculations, but actual multi-threading was still in its very early days. The resulting invokeLater concept works, but comes with a strong creation overhead. This is especially annoying if you frequently have to do minor things, but each time you need to create an entire new Runnable, just to get that event into the Swing thread.
A more modern approach should use a thread-safe list, like a LinkedBlockingQueue. In this case any thread can just throw the event into the queue, and other listener/GUI-Event-handlers can take them out asynchronously, without the need of synchronization or background Runnables.
Example:
You initialize a new Button that does some heavy calculation once it is pressed.
In the GUI thread the following method is called once the button is clicked:
void onClick() {
executor.submit(this.onClickAction);
}
Where executor is an ExecutorService and the onClickAction a Runnable. As the onClickAction is a Runnable that was submitted once during Button creation, no new memory is accessed here. Let's see what this Runnable actually does:
void run() {
final MyData data = doSomeHeavyCalculation();
dispatcher.dispatch(myListeners, data);
}
The dispatcher is internally using the LinkedBlockingQueue as mentioned above (the Executor uses one internally as well btw), where myListeners is a fixed (concurrent) List of listeners and data the Object to dispatch. On the LinkedBlockingQueue several threads are waiting using the take() method. Now one is woken up as of the new event and does the following:
while (true) {
nextEvent = eventQueue.take();
for (EventTarget target : nextEvent.listeners) {
target.update(nextEvent.data);
}
}
The general idea behind all this, is that for once you utilize all cores for your code, and in addition you keep the amount of objects generated as low as possible (some more optimizations are possible, this is just demo code). Especially you do not need to instantiate new Runnables from scratch for frequent events, which comes with a certain overhead. The drawback is that the code using this kind of GUI model needs to deal with the fact that multi-threading is happening all the time. This is not difficult using the tools Java gives to you, but it is an entire different way of designing your code in the first place.

AsyncTask alternative for simple cases

When I want to do something in background, if the action is very simple: Like do "something in background" and then update the UI, instead of using an AsyncTask I'm considering to use (just for faster coding):
new Thread(){
public void run(){
final ArrayList<myObjects> objects= myDatabase.queryObjects();
runOnUiThread(new Runnable() {
#Override
public void run() {
updateUIWith(objects);
}
});
}
}
But I really don't know if using "final" objects that way can result in memory leaks or have other kind of troubles.
Is using this method OK?
final only says to the compiler that you won't reallocate the objects variable in your code. There is no link between final and memory leaks.
If you use an anonymous inner class (the new Runnable...) you have to make objects final.
I am not very familiar with Android but if your updateUIWith() method does interact with UI objects, it might be an issue as I would assume UI updates need to run in a specific UI thread. If you don't update UI objects in that method then you code should be fine.
The question is: Is it a good idea to open a new thread for every little action? AsyncTask provides the convenience of the threads being managed by someone else, but when you declare a thread like you did, you're responsible for dealing with situation such as limitations on the number of threads.

Best method for threading in Android?

I have an animation in which triggers an event. This event fires a lot of computing usage and thus stutters the UI.
What I need to do is keep the thread running smoothly. When the event happens it will pass a string down to the thread, perform calculations (including using the audioRecord class) and return a boolean variable.
I have looked around and it seems AsyncTask may be the best solution, but I wanted to see if any of you had any ideas? Considering performance, Is this the best way to go?
Thanks,
Ben
Generally AsyncTask is fine.
But if you dont need to acess the UI thread for your background operation you can simply use a new thread.
new Thread(new Runnable() {
public void run() {
//do stuff
}
}).start();

Is a swingWorker guaranteed to throw a state property change event on completion?

I have a class that takes in a number of SwingWorkers and runs them one at a time in a certain order. I use a ReentrantLock to make sure that only one worker runs at a time. Normally I would always unlock in a finally clause, but I need it to stay locked until the worker completes.
nextWorker.getPropertyChangeSupport().addPropertyChangeListener("state",
new PropertyChangeListener()
{
#Override
public void propertyChange(PropertyChangeEvent evt)
{
if (evt.getNewValue().equals(SwingWorker.StateValue.DONE))
{
executionLock.unlock();
}
}
});
If this is not the case, is done() guaranteed to be called? I would prefer not to call unlock this way, as it would violate encapsulation to some degree.
Due to the nature of the project it is likely that this will come up in a code review. In that case it would be helpful to have a verifiable source. So far I have been unable to find one.
personally I tried everything possible with SwingWorker, but always ends me with done(), but I think that there no guarantee that implemented methods from Future ends correctly, still there this Bug
no idea about your code about lock/unlock another thread or process, but I suggest to use Executor for multithreading,
how to get exceptions from SwingWorker Task
personally I never ever had bad experiences with SwingWorker or some un-expected lack, but all MultiThreading Gurus told about SwingWorker for Production code never, there is still required use of Runnable#Thread instead of SwingWorker

Android - Ending activity from within rendering thread

Good afternoon.
I am unfamiliar with the activity life cycle in android and have been reading up as best as possible but I cannot figure how to solve the following in a nice manner.
I have an activity with a GLSurfaceView to draw various things on the screen. In the renderering thread for this GLSurfaceView I perform all the rendering as well as the actual update logic (I will seperate this out eventually).
The trouble I am having is from one of the "screens" drawn within the renderer I wish to end the Activity and have it call the various lifecycle methods.
Normally I might do this with System.exit(0); however ending the activity in this way does not seem to call the OnStop(); OnDestroy(); methods.
This might just be me being silly and not seeing an easy way of doing this but is there a way to access the Activity and call activity.finish(); without having to pass the reference to it all the way down?
This is probably less of an android question and more a general java problem? Sorry I am a little rusty at both. Maybe if someone could explain roughly how they handle an issue like this in their app.
You do need to obey thread safety rules and not call activity.finish() directly from your render thread. The best way to handle this is to post a runnable back onto the event queue for the UI Thread. And let that Runnable call activity.finish().
You don't have to pass the activity down to the area where you plan on stopping the activity. Here is what I'd do. Pass the activity to the class you instantiate in onCreate(). Something like:
public void onCreate( ... ) {
MyRenderer renderer = new MyRenderer( glSurface, this );
}
Then inside MyRenderer I'd do something like:
public void someMethodInRenderer() {
if( stop ) {
stop();
}
}
public void stop() {
Handler handler = new Handler();
handler.post( new Runnable() {
public void run() {
activity.finish();
}
} );
}
Notice the Handler used to post back to the UI thread. That makes it safe to call activity.finish(). I couldn't find any specific information in the docs stating it's safe or not safe to call finish() from another thread so to be on the safe side post it back.
Things to keep in mind. If someMethodInRenderer() is deep within the bowels in your program then you don't have to have access directly to the activity instance. You just need a reference so something that eventually calls to the activity to finish. So maybe there is a reference to another part of the system you are passing down to that method where you can add the stop(). So stop() and someMethodInRenderer() could be in the same class, or in different classes. That's a choice you'll have to make. Eventually this is an architecture issue you have to decide.
If the renderer thread is inside the Activity, you can use ActivityClassName.this.finish();
To address an issue I ran into:
If you finish your activity (including from another thread) via activity.finish() it is important that the render thread's onDraw() method is not blocked (happened to me due to my implementation of double buffer rendering).
In that case, only the onPause() method in the activity class got called. The methods onStop() and onDestroy() weren't called even though the app finished with a short delay.
Hope this helps anybody facing the same problem.
Edit: The reason was, that in my activity.onPause() method I called glSurfaceView.onPause() while the render thread's onDraw() was blocked.

Categories