Is there a way to rebuild the whole app include const widgets in flutter project? - widget

In my Flutter project, to improve performance I created many const widgets, these widgets will not rebuild when their parent widgets rebuild.
But after the user changes language of the app, I need to rebuild the whole app to apply the text changes.
Is there a way to force the app to completely rebuild? Thanks, any advice would be appreciated.

'Inheritedwidget` is a solution to redraw any widget when the passed value change. Even stateless and const widgets.
For translations for example, flutter already provides an InheritedWidget, which you can bind to using Localizations.of method

yes there is a way to do it. you have to do full restart (now it's called Hot Restart) in the code, the way to do it is to put your App inside a static widget(why static? because it'll be created once just to avoid the null or anything like that). and when you want to do full restart, just perform a hot-reload in that widget, after that it'll restart your app. you can use it from everywhere
here is the way :
1- first in main.dart, put the your App inside the Restart widget :
import 'package:flutter/material.dart';
import 'home.dart';
void main() {
runApp(new HotRestartController(
child: new MyApp()
));
}
2- write your hotRestartController inside the file :
class HotRestartController extends StatefulWidget {
final Widget child;
HotRestartController({this.child});
static performHotRestart(BuildContext context) {
final _HotRestartControllerState state = context.ancestorStateOfType(const TypeMatcher<_HotRestartControllerState>());
state.performHotRestart();
}
#override
_HotRestartControllerState createState() => new _HotRestartControllerState();
}
class _HotRestartControllerState extends State<HotRestartController> {
Key key = new UniqueKey();
void performHotRestart() {
this.setState(() {
key = new UniqueKey();
});
}
#override
Widget build(BuildContext context) {
return new Container(
key: key,
child: widget.child,
);
}
}
3- anytime, anywhere you can import the main.dart, and call "performHotRestart" using:
HotRestartController.restartApp(context)
have fun !

Related

could not find the coorect provider above the home widget

Hello guys i faced that problem, i don't really know how to solve it, I tried many things and saw many posts but the problem persists.
the code is too long so here is the most important part
i'll need in this class the provider (to call a function in the UpdateMarkers class) and when i go to the other page i'll use it to get a set of markers
thank you for helping me :)
class grpTile extends StatelessWidget{
final String grp_nom;
final String grp_chemin;
grpTile({#required this.grp_nom, u/required this.grp_chemin});
u/override
Widget build(BuildContext context) {
return ChangeNotifierProvider<UpdateMarkers>(
builder:(_) =>UpdateMarkers(),
Provider.of<UpdateMarkers>(context).UpdateusersLocation(grp_chemin);
Navigator.push(context,
MaterialPageRoute(builder: (context) => MapVoyagePage (g)));
The better way is place ChangeNotifierProvider higher than necessary
Without knowing your app structure, you can init in main()
You can reference official example https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple#changenotifierprovider
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => UpdateMarkers(),
child: MyApp(),
),
);
}

Edit the Outer Variable With the Class Constructor

how do i edit the chattile variable in the contructor 'tambah' as shown below:
class ChatCardList extends StatefulWidget {
List<ChatTile> chattile; //EDIT THIS
ChatCardList({Key key, this.chattile}) : super(key: key);
Future<void> _onSocketInfo_newMessage(dynamic data) async {
ChatCardList _data = new ChatCardList.tambah(data);
}
ChatCardList.tambah(String message) {
print("PESAN BARU : " + message);
this.chattile.add(message); //PUSH OBJECT
}
print(chattile); //notting added
#override
_ChatCardListState createState() => new _ChatCardListState(chattile:chattile);
}
why did that happen? is my script wrong, or is there something missing from my code?
many thanks,
Could you go back and check that this is the actual code that is causing your problem.
The code displayed here will not compile at all, so it's hard to say where the real problem is. Alternatively, describe in detail what you are actually trying to achieve.
The ChatCardList.tambah(String message) { constructor does not initialize chattile, so the value of this.chattile in the body should be null. Calling add on that will throw. Otherwise that code is perfectly fine, it is how you add to a list stored in this's chattile variable.
The Future<void> _onSocketInfo_newMessage(dynamic data) async { method creates a new ChatCardList using CharCardList.tambah, but never does anything with it (it doesn't return the value), so nobody will ever see that object or its chattile value.
Also, the print(chattile); code is outside of any function or constructor body, so it is really declaring an abstract method called print which takes a parameter named chattile. Since your class isn't abstract, that should cause a compile-time error.
So, one way to rewrite your program could be:
class ChatCardList extends StatefulWidget {
List<ChatTile> chattile; //EDIT THIS
ChatCardList({Key key, this.chattile}) : super(key: key);
Future<void> _onSocketInfo_newMessage(dynamic data) {
String message = data;
this.chattile.add(message);
}
#override
_ChatCardListState createState() => new _ChatCardListState(chattile: chattile);
}
This code doesn't introduce the tambah constructor, but instead updates the chattile list immediately in the _onSocketInfo_newMessage method. That method still needs to be called from somewhere.

angular 2 RC4 create component

So here is the problem, I am attempting to create a new component from within a service that is injected within the App Component. I need the new component to be placed within the app component html tag not outside. The thing is I really do not want the app component to have to provide anything to the service I may need to inject the service into other places and hence not have it tightly coupled to the app component. So far I have created a DIV at the end of the app component html and then used #ViewChild to read the ViewContainerRef from this element located within the app component. This is then provided to the service via a function call so that it can make use of createComponent. This allows for the NEW component to be placed within the scope of the app component, not within the body. Unfortunately this is too dependant on the app component providing the ViewContainerRef. Any ideas of how I can create the new component as described.
Code Example
app.component.html
<app-component>
<div #newCompHook></div>
</app-component>
app.component.ts
#ViewChild('newCompHook', {read: ViewContainerRef}) newCompViewRef: ViewContainerRef;
constructor(appService: AppService) {
appService.setViewRef(this.newCompViewRef);
}
app.service.ts
private myViewRef;
constructor(private compiler: ComponentResolver){
this.myViewRef = null;
}
public setViewRef(vr: ViewContainerRef): void {
this.myViewRef = vr; // <-- DO NOT WANT TO DO THIS !!!
}
public createNewComp(childCmp: Type): void {
if (this.myViewRef !== null){
this.compiler.resolveComponent( childCmp ).then((compFactory:ComponentFactory) => this.myViewRef.createComponent(compFactory) )
}
}
createNewComp is called by an external source and may or may not provide the childCmp type to be resolved.
So any ideas of how I can do this without needing to provide anything from the app component ???
If you need to have the viewContainerRef in your service that is the only solution...
But it is not a good practice to generate HCI components in a service. It's the role of other components.
Let's take an exemple : your server send you a list of objects (a list of strings for exemple) and you want to generate a button for each string.
In your service you just manage the string list :
#Injectable()
export class MyService {
private myModel : Array<String> = new Array();
public get MyModel () : Array<String> {
return this.myModel;
}
/// Assume you have method in the service to populate the model...
}
Then it's your component which generate the HCI :
export class AppComponent {
/// Use dependency injection to get service :
constructor (private _myService : MyService){}
public get MyModel () : Array<String> {
return this.myService.MyModel;
}
}
Finally in your component template :
<div>
<ul>
<li *ngFor="let s of MyModel">
<!-- Button with your model text -->
<button>s</button>
</li>
</ul>
</div>
That is a better solution than generate the components in the service because just imagine you don't want buttons list but a togglebuttons list in your HCI, here you just have to change the HTML. The service is still the same, and the components typescipt part is still the same too !

How to set the scope for a customized widget in SonarQube?

I created a custom widget in Sonar to show some data for a particular project. There are 3 projects in the list and only one of them should display this widget.
I tried setting the Widget Scope #WidgetScope(value = PROJECT). Also tried not setting anything as default scope is supposed to be Project.
I'm using v5.1.2 SonarQube.
But it still shows up on all the projects with the same data.
Here is the code I'm using:
import org.sonar.api.web.AbstractRubyTemplate;
import org.sonar.api.web.Description;
import org.sonar.api.web.RubyRailsWidget;
import org.sonar.api.web.UserRole;
import org.sonar.api.web.WidgetCategory;
import org.sonar.api.web.WidgetProperties;
import org.sonar.api.web.WidgetProperty;
import org.sonar.api.web.WidgetPropertyType;
import org.sonar.api.web.WidgetScope;
import org.sonar.api.resources.Project;
import static org.sonar.api.web.WidgetScope.PROJECT;
#UserRole(UserRole.USER)
#Description("An Internal Plugin to display some data in a project")
#WidgetCategory("some-data Plugin")
#WidgetScope(value = PROJECT)
#WidgetProperties({
#WidgetProperty(key = "Index",type=WidgetPropertyType.STRING
),
})
public class OneMoreRubyWidget extends AbstractRubyTemplate implements RubyRailsWidget {
#Override
public String getId() {
return "SomeData";
}
#Override
public String getTitle() {
return "SomeData";
}
protected String getTemplatePath() {
return "/example/somedata.html.erb";
}
}
Is there any way I can get the "project name" from the Sonar Dashboard so that I can return different values in the widget for different projects?
Your best bet is to suppress display of the widget when there's no relevant data, then store data only for relevant projects.
Several widgets do conditional display already. Take a look at this Widget Lab widget which makes display conditional.

Castle Windsor - how to resolve by name?

My application uses the "SignalR" client/server comms framework. If you aren't familiar with it, the server-side app typically contains one or more "hub" classes (similar to asmx web services), each providing methods that can be called by a client. During startup, the client needs to first create a connection, then create a "proxy" for each hub that it will need to talk to, e.g.:-
var hubConnection = new HubConnection("http://...");
var fooHubProxy = hubConnection.CreateHubProxy("FooHub");
var barHubProxy = hubConnection.CreateHubProxy("BarHub");
...etc...
The string parameter passed to CreateHubProxy() is the name of the server-side hub class. The method return type is IHubProxy.
It feels like I should be able to utilise Windsor here, but I'm struggling to find a solution. My first thought was to instantiate the hub proxies and register these instances with Windsor (by name), e.g.
var fooHubProxy = hubConnection.CreateHubProxy("FooHub");
container.Register(Component.For<IHubProxy>().Instance(fooHubProxy).LifestyleSingleton().Named("FooHub"));
...etc...
The problem is that when a class needs a hub proxy, the only way to resolve it by name is to use service locator pattern, which isn't recommended. What other Windsor features (e.g. typed factories, etc.) might be useful here?
Edit
I've just found Windsor's .UsingFactoryMethod, and am wondering if this would work, to simplify hub registration:
container.Register(Component.For<IHubProxy>()
.UsingFactoryMethod((kernel, context) => hubConnection.CreateHubProxy("FooHub"))
.LifestyleSingleton()
.Named("FooHub"));
I guess I still have the problem of how to resolve by name though.
Two years later, but I have a more elegant solution for other people that stummble accross this problem too.
It is possible to use TypedFactory facility and adapt it to you needs like here.
first create the factory interface (only! no need for the actual implementation, castle will take care of that):
public interface IHubProxyFactory
{
IHubProxy GetProxy(string proxyName);
}
Now we need a class that extend the default typed facotory and retreives the component's name from the input (proxyName):
class NamedTypeFactory : DefaultTypedFactoryComponentSelector
{
protected override string GetComponentName(MethodInfo method, object[] arguments)
{
string componentName = null;
if (arguments!= null && arguments.Length > 0)
{
componentName = arguments[0] as string;
}
if (string.IsNullOrEmpty(componentName))
componentName = base.GetComponentName(method, arguments);
return componentName;
}
}
And then register the factory with castle and specify that your NamedTypeFactory will be used:
Component.For<IHubProxyFactory>().AsFactory(new NamedTypeFactory())
Now every class can get the factory interface in its constructor:
public class SomeClass
{
private IHubProxy _fooHub;
private IHubProxy _barHub;
public SomeClass(IHubProxyFactory hubProxyFactory)
{
_fooHub = hubProxyFactory.GetProxy("FooHub");
_barHub = hubProxyFactory.GetProxy("BarHub");
}
}
Okay, I think I've found a possible solution, partly using the approach detailed here which shows how it is possible to register Func<>s with Windsor.
First, I register a delegate (Func<>) that uses the container to resolve by name:-
Container.Register(Component.For<Func<string, IHubProxy>>()
.Instance(name => Container.Resolve<IHubProxy>(name))
.LifestyleSingleton());
Think of this as an IHubProxy "factory".
Next, I register my hub proxies as detailed in my original question:-
container.Register(Component.For<IHubProxy>()
.UsingFactoryMethod((kernel, context) => hubConnection.CreateHubProxy("FooHub"))
.LifestyleSingleton()
.Named("FooHub"));
container.Register(Component.For<IHubProxy>()
.UsingFactoryMethod((kernel, context) => hubConnection.CreateHubProxy("BarHub"))
.LifestyleSingleton()
.Named("BarHub"));
Here is an example of a class that needs instances of the hub proxies:-
public class SomeClass
{
private IHubProxy _fooHub;
private IHubProxy _barHub;
public SomeClass(Func<string, IHubProxy> hubProxyFactory)
{
_fooHub = hubProxyFactory("FooHub");
_barHub = hubProxyFactory("BarHub");
}
}
Untried so far, but it looks promising. It's a clever solution but injecting the Func<> feels a little hacky, so I would still be keen to hear of other possible solutions to my problem.
I just used a similar method to yours. I use a typed Factory. Advantage is I have type safety for my hubs. Registering the hubs is the same. The rest differs a bit but is technical the same.
IServiceFactory {
IHubProxy GetFooHub();
IHubProxy GetBarHub();
}
And Registration:
Container.AddFacility<TypedFactoryFacility>();
Container.Register(Component.For<IServiceFactory>().AsFactory());
Usage:
public class SomeClass
{
private IHubProxy _fooHub;
private IHubProxy _barHub;
public SomeClass(IServiceFactry hubProxyFactory)
{
_fooHub = hubProxyFactory.GetFooHub();
_barHub = hubProxyFactory.GetBarHub();
}
}
Btw. Factory.Get"Name"() resolves by name.