In all the examples I have seen with view models in combination with Jetpack Compose, one usually stores a state in the view model as MutableStateFlow and then applies collectAsState in the compose function in order to get a Compose state.
My question: Why not store the state directly in the view model, and not some flow? E.g.
class MyViewModel: ViewModel() {
val showDialog = mutableStateOf(false)
}
#Compose
fun MyScreen(viewModel: MyViewModel) {
Button(onClick = { viewModel.showDialog = true })
if (viewModel.showDialog) {
AlertDialog(...)
}
}
The above code seems to run as intended. Is this a valid solution then?
Yes it certainly is. I don't know where you saw those examples, but this is indeed the recommended practice. You can check the State Codelab; it demonstrates how to replace the LiveData objects to mutableStateOf inside the viewmodel. Also, as far as the usage of LiveData and Flow is concerned, it is mainly for interoperability, as far as I know. The apps which are not fully built in Compose, but are being transferred, or apps which plan to use the view system alongside Compose. mutableStateOf is only for Jetpack compose and hence, developers will want to use LiveData in such cases. However, if you are building a brand new project, and want it to be composed of only Compose, then definitely go for what you've mentioned in the question. It is the correct way.
Using mutableStateOf() in a view model will work, but this is no longer the best approach.
If you look at the latest version of the official documentation, including the Now in Android reference app, view models should stay data-centric and therefore use the data-centric MutableStateFlow instead of the Compose-centric mutableStateOf().
Android Developer Guide – Foundation: Screen UI state
Android Developer Guide – App Architecture: Mutating the UI state from background threads
Now in Android – View Model
Now in Android - Screen
Using MutableStateFlow also makes much more sense from a unit test perspective. When testing a view model in isolation, any dependency on Compose (or other UI-centric packages and classes) should be a red flag. In other words, why would you need any Compose dependencies when testing a view model?
I think it is better to use MutableStateFlow rather than mutableStateOf of Compose in ViewModel.
ViewModel should be independent of UI. It is not a good choice to use Compose in VM.
MutableStateFlow is multi-thread safe. You can use MutableStateFlow.update{} to update it in any thread or any coroutine context. However, mutableStateOf is not. You should use Snapshot.withMutableSnapshot{} to guarantee atomic updates in a multi-thread environment. See official document.
PS: viewModelScope is hardcoded to Dispatcher.Main, so in most case it's OK to use mutableStateOf.
It's hard to be activity-level lifecycle aware if you use mutableStateOf directly in ViewModel. There is no direct way to notify the upstream data source to stop updating when the application is switched to the background. For Flow Compose provides a extend function collectAsStateWithLifecycle(), see the blog for details.
Of course, if this is a simple program, I think it is acceptable to use Compose state directly in ViewModel (Some official documentation does the same).
Flow comes from kotlinx.coroutines it's used to observe async changes, while State is for updating compose UI changes. You're to use Flow regardless of UI if you're following subscribe to stream for changes pattern. Again, you can follow some complicated/incomplete pattern, but why would you?
Related
I started using project reactor. Does anyone know how can I pass thread local variables from one thread to another? I saw some methods on Hooks.java but could not figure out what is the recommended way of doing this. Can someone point me to some documentation or with a code snippet on how to do it. Thanks.
I have a working example in this github repository based on the spring-cloud-sleuth's implementation: https://github.com/gumartinm/JavaForFun/tree/master/SpringJava/WebReactive/spring-webreactive-reactor-context-enrich
The key classes are: ContextCoreSubscriber.java, SubscriberContext.java, ThreadContextEnrichmentAutoConfiguration.java and UsernameFilter.java
ContextCoreSubscriber.java:
Enables you to fill the Mapped Diagnostic Context: MDC
SubscriberContext.java:
Helper class for inserting data in the Reactor's Context.
ThreadContextEnrichmentAutoConfiguration.java:
In charge of configuring the Reactor's Hooks: Hooks.onEachOperator
UsernameFilter.java:
Example where we want to register the username information based on some HTTP header.
Reactor doesn't guarantee that the processing done by a Flux or Mono chain of operators will stick executing on a single thread. On the contrary, it performs work-stealing and lets the user switch execution context.
As such, using ThreadLocal is not very adapted to Reactor.
There is currently some work done in 3.1.0 towards providing an equivalent, at least for library authors that use Reactor, but nothing definite in place yet.
Keep your eyes peeled for 3.1.0, that should be the main theme of that release (and will probably be the focus of the second upcoming milestone, M2).
I want to build an application server with Dart. The httpServer in the dart:io library is certainly a good starting point for that. But I struggle with the task to "deploy" an application without restarting the server process.
To be more precise: I want to have something like a servlet container in Java, like Tomcat, into which I can easily deploy or redeploy an application without restarting the container. I thought I could utilize the mirror system, which allows me in principle to load a library and its contained classes from the filesystem. But unfortunately it seems that I cannot re-load the library. When I add for example a new class to the library, or change the coding of an existing class, a new reflection of the library without restarting the dart process, does not reflect the changes. Only when I stop the process and restart it again, the changes are visible.
So: is there a way to scrub the mirror system and let it load the library and its classes again, within the same Dart process?
I think isolates are a good fit for this requirement.
I haven't used them myself much yet but as far as I know you can load and unload them dynamically.
The documentation is not very extensive yet.
A few things I found:
https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/dart-isolate
Recent documentation about Dart Isolates
https://www.youtube.com/watch?v=TQJ1qnrbTwk
https://www.youtube.com/watch?v=4GlK-Ln7HAc
So, yes, it is possible in Dart to dynamically (re-)load dart-files at runtime. Every new isolate has its own MirrorSystem. If you want to reload a dart-file you must create a new isolate and use the MirrorSystem of this isolate to iterate over the contents in the libraries known to this MirrorSystem. If your dart-file is part of a library known to the MirrorSystem, all functions and classes contained in this file are loaded and reflected anew.
This solution has some drawbacks: First, it is quite heavyweight. The programming of inter-isolate communication is cumbersome. Also it is to be seen whether the memory consumption increases with each reload. Second, the solution is not really dynamic: Isolates load only libraries that are "known" at design-time. They must be directly or indirectly imported into the dart file that contains the static function, which is called when the isolate is created.
Two ideas how the situation could be improved:
1. It would help if the spawn and the spawnUri methods of Isolate could get a list of additional libraries as parameter, which are included in the MirrorSystem of the isolate.
2. The classloaders in Java are independent of processes and threads. They just load classes. Why isn't this possible in Dart?
I'm writing something that I want to release as both a chrome extension and a firefox add-on.
The chrome extension is already available on github. I've factored my code into several modules using a module load format similar to what requirejs uses; I did this to separate the parts that were chrome-specific from the parts I hoped to re-use in the firefox add-on.
Specifically, I split up not only the backend work, but also the content scripts.
In chrome, when my content script needs to load another module, it sends a message to the background page saying "please load this module"; the script on the background page then does:
function onLoadLibrary(request, sender, sendResponse) {
var allFrames = request.allFrames || false;
chrome.tabs.executeScript(
sender.tab.id, {file: request.library.toLowerCase() + '.js',
allFrames: allFrames},
function () {
sendResponse({});
});
return true;
}
That is, I'm able to load additional javascript into the same sandbox as the content script that asked for that code. This is necessary to make module dependencies work.
In firefox, I can't figure out how to do this. I'll attach my initial content scripts through pageMods and by calling tab.attach from the "ready" event of tabs. That seems straightforward, but then if that content script needs to load more code I can't see how to do it.
There doesn't seem to be a way to access the sandbox my content script is running in from the main.js file so that I might inject more code into it. Even if I somehow kept a reference to the relevant tab instance (which only lets me inject into the top frame in any case), it appears that each new call to tab.attach puts injected code into a new sandbox. The object tab that's passed to my ready event handle isn't a real XUL tab that I could pass to require("tabs/util").getBrowserForTab; if it were, then I think I can follow through enough of the sdk code to create my own sandbox, though I'd worry about leaving accidental memory leaks behind.
I considered passing the code back to the content script through a "eval-this-code" message, but I really don't want to use eval in my extension because of security concerns; I also worry that using eval would make it difficult to impossible to get my firefox add-on approved for AMO. (Also, how would that interact when my add-on runs on sites with a Content Security Policy?)
The usage of traits to define the add-on API seems to close off access to objects such that I can't reach inside a Worker to get a reference to the sandbox my content script is executing in. At this point, it appears that I'd need to include nearly a full copy of the sdk in my add-on just to expose one method on WorkerSandbox.
Note: I'm using the Add-On sdk (the project formerly known as JetPack). I'm willing to use Components.utils.import if someone can tell me how to use that from inside an Add-On SDK-managed content script.
Content-scripts do not expose a public API to attach more scripts to a content-script sandbox after it was initialized. You should probably file an enhancement bug and state your use case, if there isn't one filed already (search first), and/or even come up with some patches yourself.
In cases where there is a DOM that your add-on own (widget), then it's just a matter of attaching another script tag.
For things like page-mods where there is no DOM you own, you're left with a couple of options, none of which is really satisfying. As you already found out yourself, the use of traits prohibits you from accessing "private" properties/methods.
Fork page-mod/tab/content-worker to provide the functionality you need. That would require creating your own copies of the modules and expose the necessary APIs to inject scripts into existing workers.
This is has a steep learning curve (but given that you already figured out details such as traits, should be doable for you), but more importantly hard to maintain as you need to make sure you keep up with the upstream. And AMO editors will not like you very much for it :p
On the plus side, you could try to get your stuff committed upstream, fixing this problem for everybody and become a hero to many authors using the Add-on SDK.
The eval method you propose. Not only is this eval a major source for security issues, but it also may be a performance killer, as right now IIRC evaled code will not use the JIT. And, of course, it will make us AMO editors cringe, even if used "correctly".
Do not use lazy loading at all, and specify all content scripts from the very beginning. This is what add-ons usually do (I'm almost inclined to say "always"). However, this conflicts with your current design, and depending on your add-on may pose a serious performance penalty for loading stuff you didn't really need in the end.
You could use the require mechanism to have most scripts as SDK module and not content-scripts. This is not always feasible, of course, e.g. when dealing with code that would normally modify the DOM in your content-script, but might work for some other stuff.
Replace page-mod, etc with your own Greasemonkey-like, enhanced API. This means lots of work, it is error-prone, security-sensitive and has to be maintained. So, it's not really a viable solution, IMO...
Components.utils.import does not help you. It isn't available to content-scripts anyway.
I just played around a bit with Lua and tried the Koneki eclipse plugin, which is quite nice. Problem is that when I make changes in a function I'm debugging at the moment the changes do not become effective when saving the changes. So I'm forced to restart the application. Would be so nice if I could make changes in the debugger and they would become effective on the fly as for example with Smalltalk or to some extend as in hot code replacement in Java. Anybody has a clue whether this is possible?
It is possible to some degree with some limitations. I've been developing an IDE/debugger that provides this functionality. It gives you access to a remote console to execute commands in the context/environment of your running application. The IDE also supports live coding, which reloads modified code as you make changes to it; see demos here.
The main limitation is that you can't modify a currently running function (at least without changes to Lua VM). This means that the effect of your changes to the currently running function will only be seen after you exit and re-enter that function. It works well for environments that call the same function repeatedly (for example a game engine calling draw), but may not work in your case.
Another challenge is dealing with upvalues (values that are created outside of your function and are referenced inside it). There are methods to "read" current upvalues and re-create them when the (new) function is created, but it requires some code analysis to find what functions will be recreated to query them for upvalues, to get the current values, and then to create a new environment with those upvalue and assign proper values to them. My current implementation doesn't do this, which means you need to use global variables as a workaround.
There was also relevant discussion just the other day on the Lua mailing list.
This question describes two approaches of solving the sophisticated architectural problem related to ASP.NET MVC. Unfortunately our team is quite new to this technology and we haven’t found any solid sources of information on this particular topic (except overviews where it’s said that MVC is more about separation than componentization). So as for now we are hesitating: whether our solution is appropriate or there is a different obvious way to solve this problem.
We have a requirement to make ASP.NET MVC-based design with componentization in mind. View engine Razor is also a requirement for us. The key feature here is that any level of controller’s nesting is expected (obviously thru Html.Action directive within .cshtml). Any controller could potentially obtain the data thru a webservice call (the final design can break this limitation, as it’s described below).
The issue is that the data must be obtained in async and maximum parallel fashion. E.g. if two backend calls within the controllers are independent they must be performed in parallel.
At first glance the usage of async MVC controllers could solve all the problems. But there is a hidden caveat: nested controller must be specified within cshtml only (within a view). And a .cshtml view is being parsed after the original controller finished its own async execution. So all the async operations within the nested controller will be performed in a separate async slot and therefore not in parallel with the first parent controller. This is a limitation of synchronous nature of .cshtml processing.
After a deep investigation we revealed that two options are available.
1) Have only one parent async controller which will retrieve all the data and put this data into container (dictionary or whatever). The nested controllers aren’t allowed to perform any backend calls. Instead of this they will have a reference to the initialized container with the results of all the backend calls. Bu this way the consumer of the framework must differentiate between parent and child controller which is not a brilliant solution.
2) Retrieve all the data from backends within a special async HttpModule. This module will initialize the same container which will reside, for instance within HttpContext. Obviously all the controllers in such a case will not be allowed to perform any backend calls, but they will have a unified internal structure (in comparison with #1 option).
As for now we think that the option #2 is more desirable, but we are more interested in the solid community-adopted way to solve this problem in a real enterprise-level MVC projects.
Literally any links/comments are welcomed.
[UPD] A requirement of any level of nesting of controllers came from our customer which wants a system where fully reusable MVC components will be presented. And they could be combined in any sequence with any level of nesting - as it is already done in the existing webforms-based implementation. This is a business rule for existing app that the components could be combined anyhow so we're not targeted to break this rule. As for now we think that such a component is a combination of "controller+view+metadata" where "metadata" part describes the backend calls to be performed in the scenario 1 or 2.
Why are you considering async calls here? Keep in mind if your async calls are so the asp.net threads don't get all used up since the db is taking a while to return, as soon as new requests come in they too will go to the db, thus increasing the workload and in turn gaining nothing.
To be honest though, Im having a hard time following exactly what you have in mind here. Nested controllers for...?
"The key feature here is that any level of controller’s nesting is expected"
I think I (we?) need a bit more information on that part here.
However, the warning on async still stands :)
E.g. if two backend calls within the controllers are
independent they must be performed in parallel.
If they are truly independent you might be able to use asynch JavaScript calls from the client and achieve some degree of parallelism that way.