I have an Android app made using Flutter.
Currently, most of the business logic runs on Android native Kotlin, but I love Dart so I am considering moving a lot of the logic to Flutter.
Is there any concern about converting Kotlin's coroutines to Dart's isolate?
There are no general concerns that I'm aware of. Although there are some points that you need to consider before doing the change.
The concurrency paradigm changes from multithread to single thread. This means that you should not think of changing coroutines to isolates, since you will not be using isolates so often or for the same purposes as coroutines.
Isolates are used for "extreme/unique" cases, if you want to perform a long running operation, you normally shouldn't opt out for an isolate, you should perform that with the simple async/await.
It's simpler to use async/await since you don't have to worry about resource allocations or race conditions, but at the same time it allows you to do "dirtier" things, to the responsability is on you.
Last thought on Isolates: they are a separate process so communication between isolates is only done through messages, so basic data should be passed between them and that could give you some headaches if you want to return some big data. (Of course everything is possible with serialization)
Hope this helps you to choose, if not, feel free to comment and we can discuss this further.
Related
When I design models layer, there are two way to design my interface. Synchronized or asynchronized.
A. asynchronized design:
interface Callback<T> {
void success(T t);
void failure(Throwable err);
}
interface UserAPI {
void getProfile(Callback<User> callback);
}
B. Synchronized Design
interface UserAPI {
User getProfile();
}
They both have some benefit. A is non-blocking, the UI layer can use it directly. B is blocking, but it is easy to test, the design is much simple, but the UI layer should make a thread to handle it.
I really care about agility development, easy to maintain, keep the whole project neat. Which design should I use?
Ultimately, this is more a question of what you want your API to accomplish, how easy is it to use, performance impact, etc. Asynchronous designs, when done correctly, can help with some performance and API usage restrictions. But, they also tend to be harder to implement correctly and even understand by end users. Synchronous APIs tend to be easier to understand, but come with more restrictions (as you noted with use on the UI thread.) As far as backing implementation, async can also be harder to understand and maintain. I don't think agile development models really influence this, as well as the project maintenance. I would try to ensure those working on it (employees, open source contributors, etc.) are good developers who understand both approaches, write easy to understand and well structured code, and understand the goal of the API.
My recommendation: implement an API which has both async and sync versions available. Maximum flexibility, best of both worlds. Just be sure to document both sets of APIs so users know the semantics of using both.
I think it depends on a particular task. You can't choose either way for the whole project, as it usually consists of multiple parts. As a general rule, each task should be reduced to the synchronous behavior whenever it's possible, for the sake of simplicity.
If an operation is done over a fixed period of time and isn't much
longer than other operations, you can call it synchronously in the
UI thread.
If the execution of an operation may take long or unlimited period
of time, or it depends on some external conditions (e.g. network
connection, system load) and doesn't interact with the UI layer, then I'd use the synchronous design in a background thread.
If the same operation as in the previous paragraph causes updates to the GUI, then obviously the async design should be implemented.
Internal use
I would say it depends on how you will be using this API interface. If it's going to be used internally then it's a matter of where would you like to handle background threads. It's completely up to you.
Published API
In case your API is going to be published then actually it depends on developers needs. Some like to handle threading by them self deciding if it's going to be a single thread queue, multithreaded simultaneously solution or combination of both. For them SYNC API is perfect.
On the other hand some developers may not care about threading and just want get the result as easier as possible. For them ASYNC is perfect.
Recommendation
So it's seem that most probably you will have to implement both. It's most appreciated by developers and reach wide audience. For example have a look at one of the most popular network API Retrofit. They probably had the same decision to make and they implemented SYNC and ASYNC.
RETROFIT SYNC EXAMPLE
#GET("/user/{id}/photo")
Photo getUserPhoto(#Path("id") int id);
RETROFIT ASYNC EXAMPLE
#GET("/user/{id}/photo")
void getUserPhoto(#Path("id") int id, Callback<Photo> cb);
As we know, when we update the UI from the non-ui-thread, we use Handler or AsyncTask. We can find a lot of articles on how to use these methods on the Internet. But I cannot find an explanation on why a UI element cannot be operated from the non-ui thread? Can anyone help me?
I believe this decision was made by the Android team (and many other UI frameworks for that matter) because of the following reasons
Synchronization
Security
Performance
Synchronization
The simplest reason for following a single threaded model for UI is that it is the easiest way to ensure that the User Interface is not being updated by multiple sources at once and therefore, corrupted. If you imagine that multiple threads can modify the UI, it would take each thread its own amount of time to execute a portion of its code, and with the different execution speeds generate a bad user experience.
Security
Ensuring that one thread can access the UI is also a security measure, preventing any slave threads that accidentally (or purposefully) try to corrupt the UI from doing so, simply by not allowing it.
Performance
The core fact of the matter here is that UI operations, and re-rendering and re-drawing visual layers and elements is an expensive process. It can affect the performance of the framework and cause leaks or lags with the deadlocks and synchronisation in-between. So I believe this was done for the sake of performance too :)
I suspect it's because a UI is a state machine, having multiple threads operate on a single state machine makes it difficult or impossible to reason about the current state of the UI and what transitions are available at any given time. There would be unpredictable results, so it's best to keep it separated from code executing in an AsyncTask.
If I want to make a request from an Android device to a remote service, I can use AsyncTask, AsyncTaskLoader, Intent, etc to make the a request apart from the UI thread. It seems there are a lot of options, but I am confused how to choose among them. Could you explain when and which to use? Also, are there any other options besides the ones I have mentioned?
This is an extensively discussed question, since Android provides a long list of mechanisms capable to handle service calls asynchronously, besides the one you mentioned there's also:
IntentService
Native Threads
Now, the key point in your question is "When to use it" and here would be my answer:
In software the only golden rigid rule is the "It depends rule", there's no hard rules for anything in software development there's always different ways to approach a problem in software (i guess that's the reason of the word "soft" in it...) and that's exactly why it always depends, it depends on whatever you need and although one approach might be the most common way to do it like for example "AsyncTask" it doesn't mean at all that AsyncTaks is always the way to go, it always depends on the factors and needs that affect your functionality. There's plenty of things that nowdays get executed using AsyncTaks when maybe all you need could be just a regular common Native Thread.
The only way to be able to make a decision towards the most appropiate approach would be knowing ALL the features around a tool, like for example most people 90% of the time use AsyncTaks just to run doInbackGround on separate thread, but might not even need preExecute, publishProgress, postExecute, etc, and that's something a Regular Thread could do, just like this example there's features for every single object provided in order to do remote calls, however as i already mentioned several times, it all depends on what you need and what tool fits better your needs. Remember there's no hard coded rules for "How, When, and What" to use in software, IT ALL DEPENDS, and making good decisions in that "DEPENDS" makes the difference between good developers from excellent developers...
This is a list of things i usually take on count to implement either one way or another, this list do not apply for all the scenarios but might give you an idea.
AsyncTaks- I know is a good idea to make use of asynctaks when the functionality needs to be monitored, by monitored i mean, i need to keep track of progress during my job, like (download/task progress), because that's exactly what the AsyncTask was originally created for, it was created attached to "The Task Pattern", and if i don't need to make use of at least two methods for monitoring provided by AsyncTaks like onPreExecute,onProgressUpdate, onCancelled etc. I know there might be another way to implement it.
Native Java Threads - I know is good to make use of this tool when my task is not related to any view in android at all, and do not need to be monitored (example: removing/adding data from remote database, and the response might affect just persistence elements that will not be displayed like configuration preferences)
IntentService - When i want to do a one time task in a queueprocessor fashion way, but unliked a native thread, here i would like to have some application context in order to maybe bind an activity etc...
Regards!
Is there any downside to making every one of your methods synchronized in Android?
Yes - it will end up taking out locks when you don't really want them. It won't give you thread safety for free - it'll just slow down your code and make it more likely that you'll run into deadlocks due to taking out too many locks.
You need to think about thread safety and synchronization explicitly. I usually make most classes not thread-safe, and try to limit the number of places where I think about threading.
The "make everything synchronized" approach is a common one in what I think of as the four stages of threading awareness for developers:
Complete ignorance: no synchronization, no awareness of the potential problems
Some awareness, but a belief that universal synchronization cures all ills
The painful stage of knowing where there are problems, and taking a lot of care over getting things right
The mythical stage of getting everything right naturally
Most experienced developers are in stage 3 as far as I can tell - with different levels of ease within it, of course. Using immutability, higher-level abstractions instead of the low-level primitives etc helps a lot - but ultimately you're likely to have to think a fair amount whenever you've got multiple threads which need to share state.
For example, Java Swing and Android UI both use a single threaded model where a single UI thread is responsible for updating all the UI. What made the framework designers chose one thread model over the other?
Wouldn't multiple threaded UI model potentially give you more performance albeit at the cost of more complexity? I realize that the latter is a big deal because thread related bugs are nasty but I am wondering if there are any other advantages to single-threaded model other than simplicity?
What made the framework designers chose one thread model over the other?
From the horse's mouth:
AWT was initially exposed as a normal
multi-threaded Java library. But as
the Java team looked at the experience
with AWT and with the deadlocks and
races that people had encountered, we
began to realize that we were making a
promise we couldn't keep.
This analysis culminated in one of the
design reviews for Swing in 1997, when
we reviewed the state of play in AWT,
and the overall industry experience,
and we accepted the Swing team's
recommendation that Swing should
support only very limited
multi-threading.
(Read the whole article, it explains the decision in great detail and states that the exact same problems and eventual move to a single-threaded model had even occured earlier at Xerox PARC - the place where almost everything we consider bleeding edge modern in CS was invented 30 years ago)
Wouldn't multiple threaded UI model
potentially give you more performance
albeit at the cost of more complexity?
Absolutely not, because drawing the GUI and processing user actions (which is everything the UI thread needs to do) is not going to be the bottleneck in any sane 2D application.
Wouldn't multiple threaded UI model potentially give you more performance albeit at the cost of more complexity?
Not in most cases, and that added complexity would do more harm than good the vast majority of the time. You also have to realize that the UI framework must deal with the underlying OS model as well. Sure, it could work around the model and abstract that away from the programmer, but it's simply not worth it in this case.
The amount of bugs caused by multiple threads updating the UI ad hoc would far outweigh what would be for the most part meaningless performance gains (if there were even gains, threading comes with an associated overhead of its own due to locking and synchronization, you may actually just be making the performance worse a lot of the time).
In this case it's better to use multiple threads explicitly and only when needed. Most of the time in a UI you want everything on one thread and you don't gain much if anything by using multiple threads. UI interactions are almost never a bottleneck.
No, probably not. At least not when you try to run the threads on the CPU. On the GPU there is already a lot of parallel processing in various forms. Not as much for the simple GUI work, but for fancy 3D (shading, reflections etc.)
I think it's all about deadlock prevention.
Swing's components are not considered thread-safe, and they don't have to be because of this Event Dispatcher Thread. If the UI was multi-threaded, the whole app would have to rely on every component behaving itself in a thread-safe manner, and if any didn't, then deadlocks could arise in obscure situations.
So, it's just safer.
Not only that, but the same design has been chosen by Windows Forms (& .Net), GTK, Motif, and various others. I wonder if Java would have been forced into this decision by the underlying OS APIs which they interact with. Certainly SWT is forced into this situation by Windows Forms.
For more info, "EDT" is a good place to start http://en.wikipedia.org/wiki/Event_dispatching_thread
For .NET, the equivalent of SwingWorker is known as BackgroundWorker.
They are all not single threaded anymore. The modern ones all build a scene graph now and render/compose them in different threads. A Html widget does layout calculations not only in multiple threads but multiple processes.
In general with the widespread use of MVVM pattern it makes no sense for complex models. You can update the Models from any thread. IMHO this was the major reason for it's invention not the data binding argument.
You can debate philosophically if you call this still single threaded just because the mouse/key/touch events arrive all in one thread. Manipulations happen in many places nowadays. And the GPU scene graph is rendered with thousands of parallel shaders how does this apply to the question?
This is because of the nature of an UI application.
You should read the input (Mouse or Keyboard), dispatch the events, let them process and than draw the screen again.
Try do it on multi-thread process.